操作 DataTable 需要字串索引、型別轉換,易出錯。將其轉為 IList<T> 後,享受 IntelliSense、編譯期型別檢查與物件導向優勢。
int、string、DateTime、float、double。TBToList<T>public class TBToList<T> where T : new()
{
/// 取得 DataTable 所有欄位名稱
private IList<string> GetColumnNames(DataColumnCollection dcc)
{
var list = new List<string>();
foreach (DataColumn dc in dcc) list.Add(dc.ColumnName);
return list;
}
/// 建立「欄位名 → 屬性型別」對照表
private Hashtable GetColumnType(DataColumnCollection dcc)
{
if (dcc == null || dcc.Count == 0) return null;
var colNames = GetColumnNames(dcc);
var props = typeof(T).GetProperties();
var ht = new Hashtable();
int idx = 0;
foreach (var p in props)
{
foreach (var col in colNames)
{
if (col.ToLower().Contains(p.Name.ToLower()))
{
ht.Add(col, p.PropertyType.FullName + idx++);
break;
}
}
}
return ht;
}
/// 依實體屬性順序排序欄位名稱
private IList<string> GetColumnNames(Hashtable ht)
{
var props = typeof(T).GetProperties();
var list = new List<string>();
int i = 0;
foreach (var p in props)
list.Add(GetKey(p.PropertyType.FullName + i++, ht));
return list;
}
private string GetKey(string val, Hashtable ht)
{
foreach (DictionaryEntry de in ht)
if (de.Value.ToString() == val) return de.Key.ToString();
return null;
}
/// 公開轉換入口
public IList<T> ToList(DataTable dt)
{
if (dt == null || dt.Rows.Count == 0) return null;
var props = typeof(T).GetProperties();
var ht = GetColumnType(dt.Columns);
var colNames = GetColumnNames(ht);
var list = new List<T>();
foreach (DataRow dr in dt.Rows)
{
T model = new T();
int i = 0;
foreach (var p in props)
{
object val = dr[colNames[i++]];
if (val == DBNull.Value) continue;
if (p.PropertyType == typeof(string)) p.SetValue(model, val.ToString());
else if (p.PropertyType == typeof(int)) p.SetValue(model, int.Parse(val.ToString()));
else if (p.PropertyType == typeof(DateTime)) p.SetValue(model, DateTime.Parse(val.ToString()));
else if (p.PropertyType == typeof(float)) p.SetValue(model, float.Parse(val.ToString()));
else if (p.PropertyType == typeof(double)) p.SetValue(model, double.Parse(val.ToString()));
}
list.Add(model);
}
return list;
}
}
// 實體
public class Person
{
public int ID { get; set; }
public string Name { get; set; }
public string Age { get; set; }
public string Lover { get; set; }
}
// 測試
var dt = new DataTable();
dt.Columns.AddRange(new[] { "ID", "Age", "Lover", "Name" });
dt.Rows.Add(1, "Age1", "Lover1", "Name1");
dt.Rows.Add(2, "Age2", "Lover2", "Name2");
var converter = new TBToList<Person>();
IList<Person> people = converter.ToList(dt);
// people[0].Name == "Name1"
Nullable<T>、decimal、Guid 等型別支援。Expression Tree 或 IL Emit 提升效能。AutoMapper 或 Dapper 既有生態。