摘要:LINQ - DataTable 與 List
這段時間很緩慢的持續看著 LINQ 的書籍,腦袋轉了一下覺得似乎沒有寫過 DataTable 轉 List<TResult>,或者是 List<TResult> 轉 DataTable 的轉換。若能寫出來的話,或許對日後自己所負責的專案有所幫助吧。其實實作後您就會發現,都是在玩「反映 (Reflection)」,以下就來看看唄...
步驟一:建立一個新的專案後,隨後在建立一個名為「DataTableAndListExtensions.cs」Class
步驟二:撰寫 DataTable To List<TResult> 與 List<TResult> To DataTable 的程式碼
Code:
using System.Data;
using System.Reflection;
using System.Collections;
namespace DataTableAndListInterchangeSample
{
    public static class DataTableAndListExtensions
    {
        public static DataTable ListToDataTable<TResult>(this IEnumerable<TResult> ListValue) where TResult : class, new()
        {
            //建立一個回傳用的 DataTable
            DataTable dt = new DataTable();
            //取得映射型別
            Type type = typeof(TResult);
            //宣告一個 PropertyInfo 陣列,來接取 Type 所有的共用屬性
            PropertyInfo[] PI_List = null;
            foreach (var item in ListValue)
            {
                //判斷 DataTable 是否已經定義欄位名稱與型態
                if (dt.Columns.Count == 0)
                {
                    //取得 Type 所有的共用屬性
                    PI_List = item.GetType().GetProperties();
                    //將 List 中的 名稱 與 型別,定義 DataTable 中的欄位 名稱 與 型別
                    foreach (var item1 in PI_List)
                    {
                        dt.Columns.Add(item1.Name, item1.PropertyType);
                    }
                }
                //在 DataTable 中建立一個新的列
                DataRow dr = dt.NewRow();
                //將資料足筆新增到 DataTable 中
                foreach (var item2 in PI_List)
                {
                    dr[item2.Name] = item2.GetValue(item, null);
                }
                dt.Rows.Add(dr);
            }
dt.AcceptChanges();
            return dt;
        }
        public static List<TResult> DataTableToList<TResult>(this DataTable DataTableValue) where TResult : class, new()
        {
            //建立一個回傳用的 List<TResult>
            List<TResult> Result_List = new List<TResult>();
            //取得映射型別
            Type type = typeof(TResult);
            //儲存 DataTable 的欄位名稱
            List<PropertyInfo> pr_List = new List<PropertyInfo>();
            foreach (PropertyInfo item in type.GetProperties())
            {
                if (DataTableValue.Columns.IndexOf(item.Name) != -1)
                    pr_List.Add(item);                
            }
            //足筆將 DataTable 的值新增到 List<TResult> 中
            foreach (DataRow item in DataTableValue.Rows)
            {
                TResult tr = new TResult();
                foreach (PropertyInfo item1 in pr_List)
                {
                    if (item[item1.Name] != DBNull.Value)
                        item1.SetValue(tr, item[item1.Name], null);
                }
                Result_List.Add(tr);
            }
            return Result_List;
        }
    }
}
步驟三:在 WinForm 當中驗證
Code:
namespace DataTableAndListInterchangeSample
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public class TestClass
        {
            public string uName { get; set; }
            public DateTime uDateTime { get; set; }
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            List<TestClass> DataList = new List<TestClass>()
            {
                new TestClass
                {
                    uName = "Danny",
                    uDateTime = DateTime.Now
                },
                new TestClass
                {
                    uName = "Peggy",
                    uDateTime = DateTime.Now.AddDays(1)
                }
            };
DataTable dt = DataList.ListToDataTable<TestClass>();
string f_str = string.Empty;
            for (int i = 0; i < dt.Rows.Count; i++)
            {
                for (int j = 0; j < dt.Columns.Count; j++)
                {
                    if (string.IsNullOrEmpty(f_str))
                        f_str = dt.Rows[i][j].ToString();
                    else
                        f_str += "\r\n" + dt.Rows[i][j].ToString();
                }
            }
MessageBox.Show(f_str, "系統:List To DataTable", MessageBoxButtons.OK, MessageBoxIcon.Information);
f_str = string.Empty;
List<TestClass> aaa = dt.DataTableToList<TestClass>();
            foreach (var item in aaa)
            {
                f_str += item.uName + "\r\n" + item.uDateTime + "\r\n";
            }
            MessageBox.Show(f_str, "系統:DataTable To List", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}
結果:

參考:
Linq:轉換成 DataTable
擴展方法(1) DataTable 和List 相互轉換
反映 (C# 程式設計手冊)
Reflection in C# 
Reflection技術應用