我在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的数据在哪里进行类型转换。我搜索了许多链接,但在任何地方都找不到正确的答案。
答案 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的字符串。