将datatable对象转换为列表C#

时间:2018-08-01 13:22:28

标签: c# asp.net c#-4.0

我在stackoverflow上找到了以下代码。但是我没有从根本上得到这段代码在做什么。谁能解释一下此代码的工作原理?

public static List<T> ToListof<T>(DataTable dt)
    {
        const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
        var columnNames = dt.Columns.Cast<DataColumn>()
            .Select(c => c.ColumnName)
            .ToList();
        var objectProperties = typeof(T).GetProperties(flags);
        var targetList = dt.AsEnumerable().Select(dataRow =>
        {
            var instanceOfT = Activator.CreateInstance<T>();

            foreach (var properties in objectProperties.Where(properties => columnNames.Contains(properties.Name) && dataRow[properties.Name] != DBNull.Value))
            {
                properties.SetValue(instanceOfT, dataRow[properties.Name], null);
            }
            return instanceOfT;
        }).ToList();

        return targetList;
    }

我特别想知道coloumn的数据在哪里进行类型转换。我搜索了许多链接,但在任何地方都找不到正确的答案。

2 个答案:

答案 0 :(得分:1)

它尝试在运行时动态地将数据表转换为T类型的对象列表。

var objectProperties = typeof(T).GetProperties(flags);

此行使用Reflection获取类型T的公共属性列表。

var targetList = dt.AsEnumerable().Select(dataRow =>

此行将DataTable迭代为IEnumerable,为每一行获取一个名为dataRow的实例。

var instanceOfT = Activator.CreateInstance<T>();

这将在循环内使用反射创建类型为T的新实例。这意味着将为每个dataRow创建一个新的T。

foreach (var properties in objectProperties.Where(properties => 
                  columnNames.Contains(properties.Name) 

这涵盖了我们一开始就获得的T的所有属性,它们也位于columnNames中-意味着有一列具有它们的值

  && dataRow[properties.Name] != DBNull.Value))

条件的后半部分确保该列具有一个值,并且不为NULL。

  properties.SetValue(instanceOfT, dataRow[properties.Name], null);

这使用反射,再次将数据行中的值设置为T的属性。

).ToList();

这将获取从Select语句返回的所有项目,并从中返回一个列表。

代码并不是最整洁的,但是如果您知道反射是如何工作的,则这些变量的名称就很清楚。至于第二个问题-没有强制转换,因为此代码假定DataRow中的值的类型与属性的类型匹配。否则,将引发异常。

答案 1 :(得分:1)

详细信息:

-16

这将结合public和instance标志,以便仅搜索Public非静态方法。

const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;

这将列出数据表中的所有列名称

 var columnNames = dt.Columns.Cast<DataColumn>()
    .Select(c => c.ColumnName)
    .ToList();

获取通用参数的类型,并将列出所有公共的非静态属性

var objectProperties = typeof(T).GetProperties(flags);

为DataTable中的每个数据行创建一个IEnumerable

dt.AsEnumerable().Select

这将创建一个新实例,就像您将使用var instanceOfT = Activator.CreateInstance<T>();

new

这将遍历数据表中也包含的T whos的所有属性,而不是null(例如,数据库中的DbNull)

然后调用SetValue。由于dataRow已将其返回的值存储在数据库中,因此没有强制转换。仅当属性和数据库中的类型“相同”时,此方法才有效。作为NVarchar的字符串。