实现支持属性重命名的类转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
相关产品推荐
相关产品推荐

