You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现支持属性重命名的类转DataTable扩展方法技术问询

实现类到DataTable的扩展方法(支持列别名)

嘿,这需求挺实用的!咱们可以通过自定义特性+反射的组合来实现,既灵活又能满足批量重命名的需求,下面是完整的实现步骤:

1. 定义列别名特性

首先创建一个自定义特性,用来给类的属性标记DataTable里的列名:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class ColumnAliasAttribute : Attribute
{
    public string Alias { get; }

    public ColumnAliasAttribute(string alias)
    {
        Alias = alias;
    }
}

这个特性只能标记在属性上,每个属性只能加一次,专门用来存储咱们想要的列别名。

2. 编写核心扩展方法

接下来写一个IEnumerable<T>的扩展方法,这样不管是单个实体还是集合都能直接调用:

public static class DataTableExtensions
{
    public static DataTable ToDataTable<T>(this IEnumerable<T> items, Dictionary<string, string>? additionalAliases = null)
    {
        var dataTable = new DataTable(typeof(T).Name);
        var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);

        // 处理列名:优先用特性里的别名,其次用额外传入的别名,最后用属性原名
        foreach (var prop in properties)
        {
            var aliasAttr = prop.GetCustomAttribute<ColumnAliasAttribute>();
            string columnName = aliasAttr?.Alias ?? additionalAliases?.GetValueOrDefault(prop.Name) ?? prop.Name;
            
            // 自动处理可空类型,获取底层类型避免DataTable列类型出错
            var columnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
            dataTable.Columns.Add(columnName, columnType);
        }

        // 填充数据行
        foreach (var item in items)
        {
            var row = dataTable.NewRow();
            foreach (var prop in properties)
            {
                var aliasAttr = prop.GetCustomAttribute<ColumnAliasAttribute>();
                string columnName = aliasAttr?.Alias ?? additionalAliases?.GetValueOrDefault(prop.Name) ?? prop.Name;
                
                row[columnName] = prop.GetValue(item) ?? DBNull.Value;
            }
            dataTable.Rows.Add(row);
        }

        return dataTable;
    }

    // 重载方法:支持单个实体直接转换
    public static DataTable ToDataTable<T>(this T item)
    {
        return new List<T> { item }.ToDataTable();
    }
}

这里做了两个贴心优化:

  • 支持两种别名方式:特性标记(写在类属性上,一劳永逸)和额外传入字典(临时批量修改,灵活度拉满)
  • 自动识别可空类型,避免DataTable列类型报错

3. 使用示例

以你给出的UserInfo类为例,咱们给属性加上别名:

public class UserInfo
{
    public int UserID { get; set; }
    
    [ColumnAlias("First_Name")]
    public string FirstName { get; set; }
    
    [ColumnAlias("Last_Name")]
    public string LastName { get; set; }
    
    // 这个属性暂时用原名,后面可以临时修改
    public string LoginName { get; set; }
}

然后调用扩展方法:

// 单个实体转换
var user = new UserInfo 
{ 
    UserID = 1, 
    FirstName = "John", 
    LastName = "Doe", 
    LoginName = "johndoe" 
};
DataTable singleUserTable = user.ToDataTable();

// 集合转换,同时临时给LoginName指定别名"Login"
var userList = new List<UserInfo> { 
    user, 
    new UserInfo { UserID = 2, FirstName = "Jane", LastName = "Smith", LoginName = "janesmith" } 
};
var tempAliases = new Dictionary<string, string> { { "LoginName", "Login" } };
DataTable userTable = userList.ToDataTable(tempAliases);

这样生成的DataTable里,FirstName会变成First_Name,LastName变成Last_Name,LoginName会变成Login,完美符合你的需求!

额外小功能(可选)

如果需要忽略某些属性不生成列,可以再加一个IgnoreColumnAttribute,然后在扩展方法里过滤掉标记了该特性的属性,有需要的话随时可以扩展~

内容的提问来源于stack exchange,提问作者Neeraj Kumar Gupta

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 04:05:02