三层架构中我们通常使用实体对象Entity(数据传输对象)在各层之间传递数据。具有整体结构更清晰,强类型,更抽象等优点,但在UI的数据绑定时,DataTable又提供众多强大、实用的功能。如何做到二者兼顾。
在最近做的一个案子里,需要绑定实体数组比如Materiel[]绑定到界面(winform/webform都有),虽然可以直接绑定数组到GridView,但排序,过滤,查找等操作在数组里不是很方便。所以想借用DataTable做数据源。
最简单的方法就是手动建一个DataTable。为每个Materiel的property建一个Column,然后指明其数据类型。建好Table之后,循环为每个Materiel创建一个新行。如果多有几个界面,虽然做起来都差不多,但代码很难重用。
另外数据都是从WebService获取,form不允许直接访问DB,所以也不能通过ADO.net获取DataTable。
经过一段时间的考量后决定见一个专用的Utility类EntityCollectionsConvert,接口为
DataTable ToDataTable(object[] entitys);
DataTable ToDataTable<T>(List<T> entitys)
实现的原理也比较简单
1.将判断entitys不为空;
2.取出entitys的所有property
3.在DataTable中为每个property添加一列(包括元素类型)
4.为每个entity添加一行。
5.自动生成单元测试,测试,添加到项目中
public static DataTable ToDataTable(List entitys)
1 public static DataTable ToDataTable<T>(List<T> entitys)
2 {
3
4 //检查实体集合不能为空
5 if (entitys ==null|| entitys.Count<1)
6 {
7 throw new Exception("需转换的集合为空");
8 }
9
10 //取出第一个实体的所有Propertie
11 Type entityType= entitys[0].GetType();
12 PropertyInfo[] entityProperties= entityType.GetProperties();
13
14 //生成DataTable的structure
15 //生产代码中,应将生成的DataTable结构Cache起来,此处略
16 DataTable dt = new DataTable();
17 for (int i = 0; i < entityProperties.Length; i++)
18 {
19 dt.Columns.Add(entityProperties[i].Name,entityProperties[i].PropertyType);
20 }
21
22 //将所有entity添加到DataTable中
23 foreach (object entity in entitys)
24 {
25 //检查所有的的实体都为同一类型
26 if (entity.GetType()!=entityType)
27 {
28 throw new Exception("要转换的集合元素类型不一致");
29 }
30 object[] entityValues = new object[entityProperties.Length];
31 for (int i = 0; i < entityProperties.Length; i++)
32 {
33 entityValues[i] = entityProperties[i].GetValue(entity, null);
34
35 }
36 dt.Rows.Add(entityValues);
37 }
38 return dt;
39 }