Generic ListとDataTableを相互変換するC#コード
C#でGeneric List型でデータを取得してきたもののDataTable型にして使いたい場合がたまにある。そのときに相互に変換するメソッドを組んでおくと楽だ。
LINQが使えるようになってからGeneric List型を多用するコードを多く書くようになってきた。LINQでデータベースなどから値を取得するクエリーを記述し、ToListメソッド一発でデータを取得してList型にしてくれる。なんて便利な世の中になったことだろう。
だが、古いコードを保守しているとDataTable型でデータを渡したいことが多い。だからといってデータのクラスごとに変換コードをいちいち書くのも面倒である。そんなときにList型とDataTable型の変換メソッドを用意しておくと便利だ。リフレクションを使うと簡単に実現できる。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
using System.Collections;
namespace ListToDataTableTest
{
class Item
{
public int ID { get; set; }
public string Name { get; set; }
public double Value { get; set; }
public DateTime UpdateDateTime { get; set; }
}
class Program
{
private static DataTable ConvertToDataTable<T>(T list) where T : IList
{
var table = new DataTable(typeof(T).GetGenericArguments()[0].Name);
typeof(T).GetGenericArguments()[0].GetProperties().
ToList().ForEach(p => table.Columns.Add(p.Name, p.PropertyType));
foreach (var item in list)
{
var row = table.NewRow();
item.GetType().GetProperties().
ToList().ForEach(p => row[p.Name] = p.GetValue(item, null));
table.Rows.Add(row);
}
return table;
}
private static T ConvertToList<T>(DataTable table) where T : IList, new()
{
var list = new T();
foreach (DataRow row in table.Rows)
{
var item = Activator.CreateInstance(typeof(T).GetGenericArguments()[0]);
list.GetType().GetGenericArguments()[0].GetProperties().ToList().
ForEach(p => p.SetValue(item, row[p.Name], null));
list.Add(item);
}
return list;
}
static void Main(string[] args)
{
// テストデータを用意
var list = new List<Item>();
for (int i = 0; i < 20; i++)
{
list.Add(new Item() { ID = i, Name = "Name of " + i.ToString(),
Value = i, UpdateDateTime = DateTime.Now });
}
// ListをDataTableへ
var resultTable = ConvertToDataTable<List<Item>>(list);
// DataTableをListへ
var resultList = ConvertToList<List<Item>>(resultTable);
}
}
}