いろいろ備忘録日記

主に .NET とか Go とか Flutter とか Python絡みのメモを公開しています。

FileHelpers入門記-03 (結果をDataTableにマッピング)(DataTable, AsDT, DataRowComparer)


今回は、結果をDataTableで受け取る方法についてです。


前回までのやり方は、結果を配列として受け取っていました。
これはこれでいいのですが、場合によってはDataTableで取得できた方が
便利な場合もあります。


FileHelpersでは、FileHelperEngineクラスにて以下のメソッドが定義されています。

  • ReadFileAsDT
    • ファイルを指定してDataTableを取得
  • ReadStreamAsDT
    • Streamを指定してDataTableを取得
  • ReadStringsAsDT
    • 文字列を指定してDataTableを取得

なお、XXXXAsDTのAsDTを除いたメソッド名もあります。
こちらは、配列で結果を受け取る版のメソッドです。


てことで、以下サンプルです。
利用するファイルは、第一回目で利用したPersons.csvを利用しています。

using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using FileHelpers;
using Gsf.Lib.Utils;

namespace FileHelpersSamples3 {

    class Program {

        const string DATA_FILE = @".\Persons.csv";

        public void Execute() {
            //
            // エンジンを構築.
            //
            FileHelperEngine engine = new FileHelperEngine(Encoding.GetEncoding("sjis"));

            //
            // データ読み取り. (配列版)
            //
            Person persons = engine.ReadFile(DATA_FILE);
            persons.ToList().ForEach(Console.WriteLine);

            //
            // データ読み取り.(DataTable版)
            //
            DataTable table = engine.ReadFileAsDT(DATA_FILE);            

            //
            // データ読み取り.(DataTable版-2)
            //
            DataTable table2 = null;
            using (TextReader reader = new StreamReader(DATA_FILE, Encoding.GetEncoding("sjis"))) {
                table2 = engine.ReadStreamAsDT(reader);
            }

            //
            // データ読み取り.(DataTable版-3)
            //
            DataTable table3 = engine.ReadStringAsDT(File.ReadAllText(DATA_FILE, Encoding.GetEncoding("sjis")));

            //
            // データ表示.
            //
            new { table, table2, table3 }.ToList().ForEach {0}", table.AsEnumerable().SequenceEqual(table2.AsEnumerable(), DataRowComparer.Default">*1;
            Console.WriteLine("table2 == table3 ?? => {0}", table2.AsEnumerable().SequenceEqual(table3.AsEnumerable(), DataRowComparer.Default));
        }

        static void Main(string[] args) {

            (new Program()).Execute();

            Console.WriteLine("Press any key to exit...");
            Console.ReadKey();
        }
    }

    [DelimitedRecord(",")]
    public class Person {
        public int Id;

        public string Name;

        [FieldNullValue(-1)]
        public int Age;

        public string Tel;

        [FieldConverter(ConverterKind.Date, "yyyy/MM/dd hh:mm:ss")]
        public DateTime Birthday;

        public override int GetHashCode() {
            return this.ToString().GetHashCode();
        }

        public override bool Equals(object obj) {
            if (base.Equals(obj)) {
                return true;
            }

            return (this.ToString() == ( (Person) obj).ToString());
        }
        public override string ToString() {
            return string.Format("Id={0},Name={1},Age={2},Tel={3},BirthDay={4}", Id, Name, Age, Tel, Birthday);
        }
    }
}

#region My-Library
namespace Gsf.Lib.Utils {

    public static class DataTableExtensions {

        public static void Dump(this DataTable table) {
            ObjectDumper.Instance.Dump(table);
        }
    }

    public class ObjectDumper {

        #region Fields
        protected Dictionary> _specializedFuncMappings;
        protected Dictionary> _genericFuncMappings;
        private static ObjectDumper _self = new ObjectDumper();
        #endregion

        #region Constructor
        private ObjectDumper() {
            InitializeSpecializedFuncMappings();
            InitializeGenericFuncMappings();
        }
        #endregion

        #region Public Methods
        public static ObjectDumper Instance {
            get {
                return _self;
            }
        }

        public virtual void Dump(object o) {
            Dump(o, Console.Out);
        }

        public virtual void Dump(object o, TextWriter writer) {
            writer.WriteLine(ToString(o));
        }

        public virtual string ToString(object o) {

            string result = string.Empty;

            if (o == null) {
                return result;
            }

            return GetValue(o);
        }
        #endregion

        #region Protected Methods
        protected virtual void InitializeSpecializedFuncMappings() {
            if (_specializedFuncMappings == null) {
                _specializedFuncMappings = new Dictionary>();
            }

            _specializedFuncMappings[typeof(Control)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    Control ctl = o as Control;

                    if (ctl.HasChildren) {
                        result = string.Format("{0}={1}", ctl.Name, GetValue(ctl.Controls));
                    } else {
                        result = string.Format("{0}={1}", ctl.Name, ctl.Text);
                    }
                }

                return result;
            };

            _specializedFuncMappings[typeof(DataRow)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    DataRow row = o as DataRow;

                    List list = new List();
                    foreach (DataColumn col in row.Table.Columns) {
                        list.Add(string.Format("{0}", GetValue(row[col])));
                    }

                    result = string.Join(",", list.ToArray());
                    result = string.Format("{0},[{1}]", result, row.RowState);
                }

                return result;
            };

            _specializedFuncMappings[typeof(DataRowView)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    DataRowView rowView = o as DataRowView;
                    if (rowView.Row != null) {
                        DataRow row = rowView.Row;
                        result = GetValue(row);
                    }
                }

                return result;
            };

            _specializedFuncMappings[typeof(DataColumn)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    DataColumn col = o as DataColumn;
                    result = col.ColumnName;
                }

                return result;
            };

            _specializedFuncMappings[typeof(DataTable)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    DataTable tbl = o as DataTable;

                    List colList = new List();
                    foreach (DataColumn col in tbl.Columns) {
                        colList.Add(GetValue(col));
                    }

                    List rowList = new List();
                    foreach (DataRow row in tbl.Rows) {
                        rowList.Add(GetValue(row));
                    }

                    result = string.Format("{0}{1}", string.Join(",", colList.ToArray()), Environment.NewLine);
                    result += string.Join(Environment.NewLine, rowList.ToArray());
                }

                return result;
            };

            _specializedFuncMappings[typeof(BindingSource)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    BindingSource bs = o as BindingSource;
                    result = GetValue(bs.DataSource);
                }

                return result;
            };
        }

        protected virtual void InitializeGenericFuncMappings() {
            if (_genericFuncMappings == null) {
                _genericFuncMappings = new Dictionary>();
            }

            _genericFuncMappings[typeof(IList)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    IList l = o as IList;

                    List list = new List();
                    foreach (object elem in l) {
                        list.Add(string.Format("({0})", GetValue(elem)));
                    }

                    result = string.Join(",", list.ToArray());
                    result = string.Format("[{0}]", result);
                }

                return result;
            };

            _genericFuncMappings[typeof(IDictionary)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    IDictionary dict = o as IDictionary;

                    List list = new List();
                    foreach (object key in dict.Keys) {
                        list.Add(string.Format("({0}={1})", GetValue(key), GetValue(dict[key])));
                    }

                    result = string.Join(",", list.ToArray());
                    result = string.Format("{{{0}}}", result);
                }

                return result;
            };

            _genericFuncMappings[typeof(ICollection)] = (o) => {
                string result = string.Empty;

                if (o != null) {
                    ICollection collection = o as ICollection;

                    List list = new List();
                    foreach (object elem in collection) {
                        list.Add(string.Format("({0})", GetValue(elem)));
                    }

                    result = string.Join(",", list.ToArray());
                    result = string.Format("[{0}]", result);
                }

                return result;
            };
        }

        protected virtual string GetValue(object o) {
            string result = string.Empty;

            result = GetValueCore(_specializedFuncMappings, o);
            if (string.IsNullOrEmpty(result)) {
                result = GetValueCore(_genericFuncMappings, o);

                if (string.IsNullOrEmpty(result)) {
                    result = o.ToString();
                }
            }

            return result;
        }

        protected virtual string GetValueCore(Dictionary> mapping, object o) {
            string result = string.Empty;
            Type objectType = o.GetType();

            foreach (Type t in mapping.Keys) {
                if (t.IsAssignableFrom(objectType)) {
                    result = mapping[t](o);
                    break;
                }
            }

            return result;
        }
        #endregion

    }

}
#endregion


Gsf.Lib.Utils名前空間に含まれるクラスが混じってますが気にしないで下さい。
DataTableの出力をいちいち書くのが面倒なので、自分用のライブラリを貼り付けています。w


後、余談ですがDataRowの内容を別のDataRowと比較する際は、自前でループさせるより
DataRowComparerを利用するのが便利です。

*1:tbl) => { tbl.Dump(); Console.WriteLine(""); }); // // 同じデータか否か. // Console.WriteLine("table == table1 ?? => {0}", table.AsEnumerable().SequenceEqual(table2.AsEnumerable(), DataRowComparer.Default