在实际项目中,经常会用到数据之间的相互转换,序列化和反序列化就是常见场景。这里我们只简单聊聊实体类和DataTable之间的相互转换,可以用于不同业务场景使用。
目录
- 1、DataTable转Model
- 2、Model转DataTable
- 3、反射概念
- 3.1、Type 类型
- 3.2、Assembly 程序集
- 3.3、MemberInfo 成员信息
- 3.4、PropertyInfo 属性信息
1、DataTable转Model
要将C# DataTable 转换为 Model 实体类,你可以使用反射来获取 DataTable 的列和值,并通过实例化 Model 类来赋值。
1)将 DataTable 转换为 Model 类
- 示例代码
using System;
using System.Collections.Generic;
using System.Data;
using System.Reflection;
public static class DataTableExtensions
{
public static List<T> ToList<T>(this DataTable dataTable) where T : class, new()
{
List<T> list = new List<T>();
foreach (DataRow row in dataTable.Rows)
{
T obj = new T();
foreach (DataColumn col in dataTable.Columns)
{
PropertyInfo property = typeof(T).GetProperty(col.ColumnName);
if (property != null && row[col] != DBNull.Value)
{
property.SetValue(obj, row[col]);
}
}
list.Add(obj);
}
return list;
}
}
2) DataTable 转换为指定的 Model 实体类
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Id", typeof(int));
dataTable.Columns.Add("Name", typeof(string));
dataTable.Columns.Add("Age", typeof(int));
dataTable.Rows.Add(1, "John", 25);
dataTable.Rows.Add(2, "Jane", 30);
dataTable.Rows.Add(3, "Mike", 40);
List<Person> persons = dataTable.ToList<Person>();
- 运行效果
上述代码将会创建一个包含了 DataTable 数据的 Person 实体类的 List。每个列的数据将会分配给 Person 对应的属性。
请注意,上述示例中的 Person 类只是一个示例,你可以根据自己的需求创建自定义的实体类,并根据 DataTable 的列名称和类型匹配属性。另外,还需确保对应的属性存在,并且列的值类型与属性类型兼容。
2、Model转DataTable
要将C# 实体通过反射转换为 DataTable,可以使用System.Reflection命名空间中的类来访问实体的属性和值,并将其添加到 DataTable 中。
1)使用反射来转换实体为 DataTable
using System;
using System.Data;
using System.Reflection;
public static class EntityExtensions
{
public static DataTable ToDataTable<T>(this T[] entities)
{
DataTable dataTable = new DataTable(typeof(T).Name);
PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo propInfo in properties)
{
dataTable.Columns.Add(propInfo.Name, propInfo.PropertyType);
}
foreach (T entity in entities)
{
object[] values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
values[i] = properties[i].GetValue(entity);
}
dataTable.Rows.Add(values);
}
return dataTable;
}
}
2)将任何实体数组转换为 DataTable
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
Person[] persons = new Person[]
{
new Person { Id = 1, Name = "John", Age = 25 },
new Person { Id = 2, Name = "Jane", Age = 30 },
new Person { Id = 3, Name = "Mike", Age = 40 }
};
DataTable dataTable = persons.ToDataTable();
- 运行效果
上述代码将会创建一个包含了Person实体数组数据的 DataTable。每个属性都会成为该 DataTable 的列,并且每个实体实例将会形成 DataTable 的一行。
请注意,上述示例中的实体类 Person 只是一个示例,你可以根据自己的需求创建自定义的实体类,并使用相应的属性和类型。
3、反射概念
C# 的反射是指在运行时获取、检查和操作程序集、类型、成员(如字段、属性、方法等)的能力。反射提供了一组类和方法,可以在运行时动态地获取程序集和类型的信息,并使用这些信息来创建对象、调用方法、访问属性等。
以下是一些关键概念和用途:
3.1、Type 类型
Type 类型是反射的核心,它表示在运行时加载的类型。Type 类型提供了获取类型信息的方法和属性,如名称、基类、实现的接口、属性、方法、字段等。利用 Type 类型,你可以动态地获取和操作类型的信息。
3.2、Assembly 程序集
Assembly 类型表示一个程序集,它是一个逻辑单元,包含可执行文件、动态链接库或代码的容器。通过反射,你可以加载和检查程序集的信息,包括类型、成员、属性等。可以使用 Assembly 类型来加载程序集、获取程序集中的类型、创建对象等。
3.3、MemberInfo 成员信息
MemberInfo 类型表示类型的成员,如字段、属性、方法、事件等。它提供了获取成员的名称、类型、访问修饰符等信息的方法。
3.4、PropertyInfo 属性信息
PropertyInfo 类型表示类型的属性,它提供了获取和设置属性值的方法和属性。
通过反射,你可以实现许多动态和灵活的功能,如:
- 动态创建对象和调用方法:在运行时根据类型信息动态创建对象,调用对象的方法。
- 动态访问和修改属性值:在运行时获取对象的属性信息,并动态修改属性值。
- 获取和检查类型信息:在运行时获取类型的信息,如名称、基类、实现的接口、成员等。
- 加载和使用外部程序集:动态加载和使用外部程序集,以便在运行时访问和操作其中的类型和成员。
- 编写通用代码:使用反射可以编写通用、灵活的代码,以适应不同类型和成员的情况。
需要注意的是,反射在一定程度上会带来性能上的损失,因为它需要在运行时进行类型信息的获取和检查。因此,在使用反射时需要权衡性能和灵活性之间的关系,并注意避免不必要的反射操作。