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

C# 反射實現 DataRow 轉 Model 通用輔助類:ModelHelper<T>

     編輯:關於C#

痛點

手寫 GetModel 將 DataRow 逐欄位賦值給實體類別,重複、易錯、維護困難。

通用解決方案


public class ModelHelper<T> where T : new()
{
    public static T ConvertModel(DataRow dr)
    {
        T model = new T();
        Type type = model.GetType();

        foreach (PropertyInfo prop in type.GetProperties())
        {
            object value = dr[prop.Name];
            prop.SetValue(model, GetDefaultValue(value, prop.PropertyType), null);
        }
        return model;
    }

    private static object GetDefaultValue(object value, Type targetType)
    {
        if (value == DBNull.Value) return null; // 或 targetType.IsValueType ? Activator.CreateInstance(targetType) : null
        return Convert.ChangeType(value, targetType);
    }
}

使用範例


var model = ModelHelper<UserInfo>.ConvertModel(dataRow);

關鍵實作細節

  1. 泛型約束 where T : new():確保有無參數建構函式。
  2. 屬性名稱 = 資料欄位名稱:依賴命名一致慣例;不一致時需加入 ColumnAttribute 映射。
  3. DBNull 處理:Convert.ChangeType 不接受 DBNull,必須先轉為 null 或預設值。
  4. 型別轉換:Convert.ChangeType 支援基本型別、DateTime, Guid, Enum 等;自訂型別需自行擴充。

已知限制與改進方向

限制改進方案
屬性名必須與欄位名完全一致引入 [Column("db_column")] Attribute,讀取映射名
不支援巢狀物件/複雜型別遞迴處理屬性型別為 Class 的情況
唯讀屬性 (無 setter) 會拋例外檢查 prop.CanWrite 跳過
效能:反射每次調用開銷緩存 PropertyInfo[]、使用 Expression.Compile 生成強型別委派、或採用 FastMember/Dapper

現代替代方案

  • Dapper:connection.Query<T>(sql) 內建高效映射。
  • AutoMapper:物件對物件映射,支援複雜轉換。
  • EF Core:完整 ORM,追蹤變更、LINQ 查詢。

結語

ModelHelper<T> 以 20 行代碼解決 80% 簡單場景的 DataRow→Model 需求,展現反射的威力。理解其原理與限制,能在選型時做出正確決策:小專案直用、中專案擴充映射屬性、大專案上成熟 ORM/Mapper。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved