首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 通用泛型將 DataTable 轉換為強型別 IList<T>

     編輯:關於C語言

動機

操作 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 既有生態。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved