将数据表对象转换为列表 C#
Convert datatable object to list C#
我在 Whosebug 上找到了以下代码。但我不明白这段代码在做什么。谁能解释一下这段代码是如何工作的?
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;
}
我特别想知道列数据在何处进行类型转换。我搜索了很多链接,但在任何地方都没有得到正确的答案。
它尝试在运行时动态地将数据表转换为类型 T 的对象列表。
var objectProperties = typeof(T).GetProperties(flags);
此行使用反射获取类型 T 的 public 属性列表。
var targetList = dt.AsEnumerable().Select(dataRow =>
此行将 DataTable 迭代为 IEnumerable,为每一行获取一个名为 dataRow
的实例。
var instanceOfT = Activator.CreateInstance<T>();
这将在循环内使用反射创建类型 T 的新实例。这意味着为每个数据行创建一个新的 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 语句返回的所有项目和 returns 它们的列表。
如果您知道反射的工作原理,代码不是最简洁的,但变量的名称非常好且清晰。至于你的第二个问题 - 没有转换,因为这段代码假定 DataRow 中的值类型与 属性 的类型相匹配。如果没有,将抛出异常。
详细信息:
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
这将结合 public 和实例标志,以便仅搜索 Public 个非静态方法。
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
这将列出数据中的所有列名称 table
var objectProperties = typeof(T).GetProperties(flags);
获取通用参数的类型并将列出所有 public、非静态属性
dt.AsEnumerable().Select
为 DataTable 中的每个数据行创建一个 IEnumerable
var instanceOfT = Activator.CreateInstance<T>();
这会像您使用的那样创建一个新实例 new
foreach (var properties in objectProperties.Where(properties => columnNames.Contains(properties.Name) && dataRow[properties.Name] != DBNull.Value))
{
properties.SetValue(instanceOfT, dataRow[properties.Name], null);
}
这将遍历 T 的所有属性,这些属性也包含在数据中table而不是 null(例如,数据库中的 DbNull)
然后调用 SetValue。由于 dataRow 已经 return 存储在数据库中的值,因此没有强制转换。这仅在 属性 和数据库中的类型为 "the same" 时才有效。作为字符串的 NVarchar。
我在 Whosebug 上找到了以下代码。但我不明白这段代码在做什么。谁能解释一下这段代码是如何工作的?
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;
}
我特别想知道列数据在何处进行类型转换。我搜索了很多链接,但在任何地方都没有得到正确的答案。
它尝试在运行时动态地将数据表转换为类型 T 的对象列表。
var objectProperties = typeof(T).GetProperties(flags);
此行使用反射获取类型 T 的 public 属性列表。
var targetList = dt.AsEnumerable().Select(dataRow =>
此行将 DataTable 迭代为 IEnumerable,为每一行获取一个名为 dataRow
的实例。
var instanceOfT = Activator.CreateInstance<T>();
这将在循环内使用反射创建类型 T 的新实例。这意味着为每个数据行创建一个新的 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 语句返回的所有项目和 returns 它们的列表。
如果您知道反射的工作原理,代码不是最简洁的,但变量的名称非常好且清晰。至于你的第二个问题 - 没有转换,因为这段代码假定 DataRow 中的值类型与 属性 的类型相匹配。如果没有,将抛出异常。
详细信息:
const BindingFlags flags = BindingFlags.Public | BindingFlags.Instance;
这将结合 public 和实例标志,以便仅搜索 Public 个非静态方法。
var columnNames = dt.Columns.Cast<DataColumn>()
.Select(c => c.ColumnName)
.ToList();
这将列出数据中的所有列名称 table
var objectProperties = typeof(T).GetProperties(flags);
获取通用参数的类型并将列出所有 public、非静态属性
dt.AsEnumerable().Select
为 DataTable 中的每个数据行创建一个 IEnumerable
var instanceOfT = Activator.CreateInstance<T>();
这会像您使用的那样创建一个新实例 new
foreach (var properties in objectProperties.Where(properties => columnNames.Contains(properties.Name) && dataRow[properties.Name] != DBNull.Value))
{
properties.SetValue(instanceOfT, dataRow[properties.Name], null);
}
这将遍历 T 的所有属性,这些属性也包含在数据中table而不是 null(例如,数据库中的 DbNull)
然后调用 SetValue。由于 dataRow 已经 return 存储在数据库中的值,因此没有强制转换。这仅在 属性 和数据库中的类型为 "the same" 时才有效。作为字符串的 NVarchar。