?C# List 转换为 DataTable 的实现方法?
以下提供两种常用方式将 List<T> 转换为 DataTable,支持泛型对象自动映射列,并处理空值和类型匹配问题。
?方法一:反射动态映射(通用型)?
通过反射自动提取对象属性作为 DataTable 的列,适用于任意类型的 List<T>。
using System.Reflection;
public static DataTable ListToDataTable<T>(List<T> list)
{
DataTable dt = new DataTable();
if (list == null || list.Count == 0)
return dt; // 处理空列表
// 获取对象属性作为列
PropertyInfo[] props = typeof(T).GetProperties();
foreach (PropertyInfo prop in props)
{
// 设置列名和数据类型(处理可空类型)
Type colType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType;
dt.Columns.Add(prop.Name, colType);
}
// 填充数据行
foreach (T item in list)
{
DataRow row = dt.NewRow();
foreach (PropertyInfo prop in props)
{
object value = prop.GetValue(item, null) ?? DBNull.Value;
row[prop.Name] = value;
}
dt.Rows.Add(row);
}
return dt;
}
?方法二:手动映射(高性能)?
针对特定类型手动定义列,避免反射性能损耗,适合固定数据结构的场景。
public static DataTable ListToDataTableManual(List<Person> persons)
{
DataTable dt = new DataTable();
// 手动定义列
dt.Columns.Add("Id", typeof(int));
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("BirthDate", typeof(DateTime));
// 填充数据行
foreach (Person person in persons)
{
DataRow row = dt.NewRow();
row["Id"] = person.Id;
row["Name"] = person.Name ?? string.Empty; // 处理空值
row["BirthDate"] = person.BirthDate.HasValue ?
person.BirthDate.Value : (object)DBNull.Value;
dt.Rows.Add(row);
}
return dt;
}
?使用示例?
?定义实体类?
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime? BirthDate { get; set; } // 可空类型
}
?转换并绑定到 DataGridView?
csharp
Copy Code
List<Person> people = new List<Person>
{
new Person { Id = 1, Name = "张三", BirthDate = new DateTime(1990, 5, 1) },
new Person { Id = 2, Name = "李四", BirthDate = null }
};
// 使用反射方法转换
DataTable dt = ListToDataTable(people);
// 绑定到 DataGridView
dataGridView1.DataSource = dt;
?关键点说明?
?特性? ?反射方法? ?手动方法?
?通用性? 支持任意 List<T> 仅限预定义类型
?性能? 反射有性能损耗,适用于数据量小或低频操作 高性能,适合大数据量或高频调用
?可维护性? 自动适应属性变化(如新增字段) 需手动维护列映射
?空值处理? 自动将 null 转换为 DBNull.Value 需显式处理可空字段
?扩展优化?
?缓存反射结果?:
若频繁转换同一类型,可缓存 PropertyInfo 数组提升性能。
private static Dictionary<Type, PropertyInfo[]> _propertyCache = new Dictionary<Type, PropertyInfo[]>();
?忽略特定属性?:
通过 Attribute 标记需要跳过的字段。
if (prop.GetCustomAttribute<IgnoreColumnAttribute>() != null)
continue;
?自定义列名?:
使用 [DisplayName("列名")] 特性覆盖默认属性名。
string columnName = prop.GetCustomAttribute<DisplayNameAttribute>()?.DisplayName ?? prop.Name;
dt.Columns.Add(columnName, colType);
?常见问题解决?
?类型不匹配错误?
确保 DataColumn 类型与属性实际类型一致(如 int? 映射为 typeof(int))。
使用 Nullable.GetUnderlyingType 处理可空类型。
?空引用异常?
在访问属性值前检查对象是否为 null。
使用 ?? 运算符提供默认值。
?性能优化?
对大规模数据使用 手动映射 或 Emit 动态生成IL代码(高级技巧)。
通过上述方法,可灵活实现 List<T> 到 DataTable 的转换,满足通用性或高性能需求。
查看更多关于?C# List 转换为 DataTable 的实现方法?的详细内容...