65.9K
CodeProject 正在变化。 阅读更多。
Home

将通用列表转换为 DataTable

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (6投票s)

2010年5月23日

CPOL

3分钟阅读

viewsIcon

123463

downloadIcon

3335

一个具有转换为 DataTable 功能的通用列表。

前言

在很多情况下,我们都会觉得需要将对象列表转换为 DataTable。 我在某种情况下特别需要这个功能。

当我们在 Web 应用程序中使用面向对象的方法时,最好将 GridView 绑定到对象的泛型列表。 在这种情况下,GridView 的排序就成了一个问题,因为 C# .NET 泛型列表类没有提供简单的排序功能。

传统上(几乎所有 .NET 文章中 GridView 的排序解决方案),我们通过将源 datatable 转换为 DataView,然后将排序后的 DataView 再次绑定到 GridView 来对 GridView 进行排序。 这对于 GridView 排序来说是一种非常简单的方法。

因此,如果我们将 GridView 绑定到对象列表,我们会觉得在排序时需要将其转换为 DataTable

由于泛型类 List 没有提供转换为 DataTable 的函数,我创建了一个具有此功能的 ABList 类。

因此,人们可以使用 ABList,就像使用 List 一样,唯一的区别是增加了一个 GetDataTable 函数。

我希望现在我已经证明了撰写本文的目的,所以我们可以继续了解 ABList 的工作原理。

引言

ABList 是一个泛型类,它继承自 System.Generics.Collections.List。 它添加了一个 public 函数 GetDataTable,从而扩展了其功能,以获得一个 DataTable,其中包含基础类的所有 public 属性作为列,并为列表中的每个对象都包含一行。

它可以用来创建一个任何数据类型的列表,无论是引用类型还是值类型。 如果基础类型是引用类型(String 除外),它将具有与该类的所有 public 属性相同的列。 如果它是值类型,那么将只有一个名为“Value”的列,它将存储 List 中变量的值。

如何使用 ABList 类

使用 ABList 类就像使用 List 类一样简单。 我们需要通过提供我们想要与 ABList 类一起使用的基础类型来定义一个变量,如下所示: 

ABList<Product> lstP = new ABList<Product>();

然后我们可以将项目添加到此列表,如下所示

lstP.Add(new Product("a", "a"));
lstP.Add(new Product("b", "b"));
lstP.Add(new Product("c", "c"));

就像我们使用 List 一样。

现在,如果我们想将我们的 List 转换为 DataTable,我们只需要调用 ABClass 中定义的新函数

DataTable dtPro = lstP.GetDataTable();

ABList 类

ABList 类继承了一个泛型类 List,它只有一个自己的函数,即 GetDataTable 函数。 以下是 ABList 的定义方式

public class ABList<T> : List<T>

很简单。

然后是 GetDataTable 函数。 我没有将 ABList 限制为仅引用类型或值类型。 因此,我们需要注意将 List 转换为 DataTable 时的两种情况,因为基础类型可以是值类型或引用类型。

首先,我们检查如果基础类型是值类型(或 string),如何获取 DataTable

在值类型中,DataTable 应包含 List 中存在的所有变量(项目)的值。 因此,我们只在 DataTable 中创建一个名为“Value”的列,并为在 List 中找到的每个项目添加一个新行,将其值保存在该行中。

if (typeof(T).IsValueType || typeof(T).Equals(typeof(string)))
{
   DataColumn dc = new DataColumn("Value");
   dt.Columns.Add(dc);
   foreach (T item in this)
   {
       DataRow dr = dt.NewRow();
       dr[0] = item;

       dt.Rows.Add(dr);
   }
}

虽然 String 是一个引用类型,但由于其行为,我们将其视为特殊情况,并且仅将其作为值类型处理。

现在,为了处理引用类型,我们需要使用 System.Reflection 命名空间的 PropertyInfo 类。

首先,我们使用反射找出基础类的所有 public 属性,如下所示

PropertyInfo[] piT = typeof(T).GetProperties();

因此,我们拥有了基础类的所有 public 属性,现在我们需要创建一个 DataTable 并将列名设置为数组 piT 中的属性名称。

foreach (PropertyInfo pi in piT)
{
   //create a datacolumn for each property
   DataColumn dc = new DataColumn(pi.Name, pi.PropertyType);

   dt.Columns.Add(dc);
}

然后,我们遍历 List 中的所有项目,并为每个项目创建一个行,并将属性值保存在相应的列中。 为了从对象(项目)获取属性的值,我们需要为我们的 PropertyInfo piT 数组中的每个属性调用 GetValue 方法。

for (int item = 0; item < this.Count; item++)
{
    DataRow dr = dt.NewRow();

     for (int property = 0; property < dt.Columns.Count; property++)
     {
        dr[property] = piT[property].GetValue(this[item], null);
     }

     dt.Rows.Add(dr);
}

历史

  • 2010 年 5 月 23 日:初始帖子
© . All rights reserved.