List<T>转换为DataTable

本文介绍了几种List<T>与DataTable之间的转换方法,包括通过属性反射来创建DataTable及填充数据的方式,以及如何将DataTable转换回List<T>。这些方法适用于C#开发人员在不同场景下进行数据结构转换的需求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

关于List<T>转换为DataTable的问题一直是开发过程中经常用到的,现从网上整理几个常用的转换方式,留作备用。

(尊重作者原创,本文代码转发自 List 与 DataTable 转换  ) 

public static class DataTableExtensions
   {
       /// <summary>
       /// 转化一个DataTable
       /// </summary>
       /// <typeparam name="T"></typeparam>
       /// <param name="list"></param>
       /// <returns></returns>
       public static DataTable ToDataTable<T>(this IEnumerable<T> list)
       {
           //创建属性的集合
           List<PropertyInfo> pList = new List<PropertyInfo>();
           //获得反射的入口
           Type type = typeof(T);
           DataTable dt = new DataTable();
           //把所有的public属性加入到集合 并添加DataTable的列
           Array.ForEach<PropertyInfo>(type.GetProperties(), p => { pList.Add(p); dt.Columns.Add(p.Name, p.PropertyType); });
           foreach (var item in list)
           {
               //创建一个DataRow实例
               DataRow row = dt.NewRow();
               //给row 赋值
               pList.ForEach(p => row[p.Name] = p.GetValue(item, null));
               //加入到DataTable
               dt.Rows.Add(row);
           }
           return dt;
       }
 
       /// <summary>
       /// DataTable 转换为List 集合
       /// </summary>
       /// <typeparam name="TResult">类型</typeparam>
       /// <param name="dt">DataTable</param>
       /// <returns></returns>
       public static List<T> ToList<T>(this DataTable dt) where T : class, new()
       {
           //创建一个属性的列表
           List<PropertyInfo> prlist = new List<PropertyInfo>();
           //获取TResult的类型实例  反射的入口
           Type t = typeof(T);
           //获得TResult 的所有的Public 属性 并找出TResult属性和DataTable的列名称相同的属性(PropertyInfo) 并加入到属性列表 
           Array.ForEach<PropertyInfo>(t.GetProperties(), p => { if (dt.Columns.IndexOf(p.Name) != -1) prlist.Add(p); });
           //创建返回的集合
           List<T> oblist = new List<T>();
 
           foreach (DataRow row in dt.Rows)
           {
               //创建TResult的实例
               T ob = new T();
               //找到对应的数据  并赋值
               prlist.ForEach(p => { if (row[p.Name] != DBNull.Value) p.SetValue(ob, row[p.Name], null); });
               //放入到返回的集合中.
               oblist.Add(ob);
           }
           return oblist;
       }
 
 
       /// <summary>
       /// 将集合类转换成DataTable
       /// </summary>
       /// <param name="list">集合</param>
       /// <returns></returns>
       public static DataTable ToDataTableTow(IList list)
       {
           DataTable result = new DataTable();
           if (list.Count > 0)
           {
               PropertyInfo[] propertys = list[0].GetType().GetProperties();
               foreach (PropertyInfo pi in propertys)
               {
                   result.Columns.Add(pi.Name, pi.PropertyType);
               }
 
               for (int i = 0; i < list.Count; i++)
               {
                   ArrayList tempList = new ArrayList();
                   foreach (PropertyInfo pi in propertys)
                   {
                       object obj = pi.GetValue(list[i], null);
                       tempList.Add(obj);
                   }
                   object[] array = tempList.ToArray();
                   result.LoadDataRow(array, true);
               }
           }
           return result;
       }
 
       /**/
       /// <summary>
       /// 将泛型集合类转换成DataTable
       /// </summary>
       /// <typeparam name="T">集合项类型</typeparam>
       /// <param name="list">集合</param>
       /// <returns>数据集(表)</returns>
       public static DataTable ToDataTable<T>(IList<T> list)
       {
           return ToDataTable<T>(list, null);
       }
 
       /**/
       /// <summary>
       /// 将泛型集合类转换成DataTable
       /// </summary>
       /// <typeparam name="T">集合项类型</typeparam>
       /// <param name="list">集合</param>
       /// <param name="propertyName">需要返回的列的列名</param>
       /// <returns>数据集(表)</returns>
       public static DataTable ToDataTable<T>(IList<T> list, params string[] propertyName)
       {
           List<string> propertyNameList = new List<string>();
           if (propertyName != null)
               propertyNameList.AddRange(propertyName);
 
           DataTable result = new DataTable();
           if (list.Count > 0)
           {
               PropertyInfo[] propertys = list[0].GetType().GetProperties();
               foreach (PropertyInfo pi in propertys)
               {
                   if (propertyNameList.Count == 0)
                   {
                       result.Columns.Add(pi.Name, pi.PropertyType);
                   }
                   else
                   {
                       if (propertyNameList.Contains(pi.Name))
                           result.Columns.Add(pi.Name, pi.PropertyType);
                   }
               }
 
               for (int i = 0; i < list.Count; i++)
               {
                   ArrayList tempList = new ArrayList();
                   foreach (PropertyInfo pi in propertys)
                   {
                       if (propertyNameList.Count == 0)
                       {
                           object obj = pi.GetValue(list[i], null);
                           tempList.Add(obj);
                       }
                       else
                       {
                           if (propertyNameList.Contains(pi.Name))
                           {
                               object obj = pi.GetValue(list[i], null);
                               tempList.Add(obj);
                           }
                       }
                   }
                   object[] array = tempList.ToArray();
                   result.LoadDataRow(array, true);
               }
           }
           return result;
       }
   }
前两种方式通过集合的 FOREACH 方法,获取泛型类型的属性和类型初始化转换的对象;

后两种为显示遍历转换源集合的属性和类型 ,然后逐一将数据更新的目的集合中。

附 foreach 方法说明:


C# 语言的 foreach 语句(在 Visual Basic 中为 For Each)隐藏了枚举数的复杂性。因此,建议使用 foreach,而不直接操作枚举数。

枚举数可用于读取集合中的数据,但不能用于修改基础集合。

最初,枚举数定位在集合中第一个元素前。Reset 方法还会将枚举数返回到此位置。在此位置上,Current 属性未定义。因此,在读取 Current 的值之前,必须调用 MoveNext 方法将枚举数提前到集合的第一个元素。

在调用 MoveNext 或 Reset 之前,Current 返回同一对象。MoveNext 将 Current 设置为下一个元素。

如果 MoveNext 越过集合的末尾,则枚举数将被放置在此集合中最后一个元素的后面,而且 MoveNext 返回 false。当枚举数位于此位置时,对 MoveNext 的后续调用也返回 false。如果上一个 MoveNext 调用返回 false,则 Current 未定义。若要再次将 Current 设置为集合的第一个元素,可以调用 Reset,然后再调用 MoveNext。

只要集合保持不变,枚举数就保持有效。如果对集合进行更改(如添加、修改或删除元素),则枚举数将失效且不可恢复,而且其行为是不确定的。

枚举数没有对集合的独占访问权;因此,枚举通过集合在本质上不是一个线程安全的过程。若要确保枚举过程中的线程安全,可以在整个枚举过程中锁定集合。若要允许多个线程访问集合以进行读写操作,则必须实现自己的同步。



好的,我可以回答你的问题。利用反射可以实现 DataTable 与 List<T> 之间的转换。 首先,我们需要定义一个通用的方法,该方法可以将 List<T> 转换DataTable,也可以将 DataTable 转换为 List<T>。该方法的实现需要借助反射机制。 下面是将 List<T> 转换DataTable 的代码: ```csharp public static DataTable ConvertToDataTable<T>(List<T> list) { DataTable table = new DataTable(); PropertyInfo[] properties = typeof(T).GetProperties(); foreach (PropertyInfo property in properties) { table.Columns.Add(property.Name, property.PropertyType); } foreach (T item in list) { DataRow row = table.NewRow(); foreach (PropertyInfo property in properties) { row[property.Name] = property.GetValue(item, null); } table.Rows.Add(row); } return table; } ``` 上面的代码中,我们首先使用反射机制获取类型 T 的所有属性信息,然后使用这些属性信息创建 DataTable 的列。接着,我们遍历 List<T> 中的每个元素,使用反射获取元素的属性值,并将这些属性值添加到 DataRow 中,最后将 DataRow 添加到 DataTable 中。 下面是将 DataTable 转换为 List<T> 的代码: ```csharp public static List<T> ConvertToList<T>(DataTable table) where T : new() { List<T> list = new List<T>(); PropertyInfo[] properties = typeof(T).GetProperties(); foreach (DataRow row in table.Rows) { T item = new T(); foreach (PropertyInfo property in properties) { if (table.Columns.Contains(property.Name)) { property.SetValue(item, row[property.Name], null); } } list.Add(item); } return list; } ``` 上面的代码中,我们同样使用反射机制获取类型 T 的所有属性信息,然后遍历 DataTable 中的每个 DataRow,使用反射设置每个 DataRow 中对应的属性值,并将 T 对象添加到 List<T> 中。 希望这些代码可以帮助你解决问题。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值