(一)通用以及泛型转换代码
先看下面关于将DataRow转换成相应的对象(通用以及泛型操作)的方法(这里仅仅是对DataRow进行转换,对于将DataTable转换成对象集合,思路基本差不多,因此本例里不再对其他的进行相关代码的编写):
2 {
3 public static object ToEntity(DataRow adaptedRow, Type entityType)
4 {
5 if (entityType == null || adaptedRow == null)
6 {
7 return null;
8 }
9
10 object entity = Activator.CreateInstance(entityType);
11 CopyToEntity(entity, adaptedRow);
12
13 return entity;
14 }
15
16 public static T ToEntity<T>(DataRow adaptedRow, T value) where T:new()
17 {
18 T item = new T();
19 if (value == null || adaptedRow == null)
20 {
21 return item;
22 }
23
24 item = Activator.CreateInstance<T>();
25 CopyToEntity(item, adaptedRow);
26
27 return item;
28 }
29
30 public static void CopyToEntity(object entity, DataRow adaptedRow)
31 {
32 if (entity == null || adaptedRow == null)
33 {
34 return;
35 }
36 PropertyInfo[] propertyInfos = entity.GetType().GetProperties();
37
38 foreach (PropertyInfo propertyInfo in propertyInfos)
39 {
40 if (!CanSetPropertyValue(propertyInfo, adaptedRow))
41 {
42 continue;
43 }
44
45 try
46 {
47 if (adaptedRow[propertyInfo.Name] is DBNull)
48 {
49 propertyInfo.SetValue(entity, null, null);
50 continue;
51 }
52 SetPropertyValue(entity, adaptedRow, propertyInfo);
53 }
54 finally
55 {
56
57 }
58 }
59 }
60
61 private static bool CanSetPropertyValue(PropertyInfo propertyInfo, DataRow adaptedRow)
62 {
63 if (!propertyInfo.CanWrite)
64 {
65 return false;
66 }
67
68 if (!adaptedRow.Table.Columns.Contains(propertyInfo.Name))
69 {
70 return false;
71 }
72
73 return true;
74 }
75
76 private static void SetPropertyValue(object entity, DataRow adaptedRow, PropertyInfo propertyInfo)
77 {
78 if (propertyInfo.PropertyType == typeof(DateTime?) ||
79 propertyInfo.PropertyType == typeof(DateTime))
80 {
81 DateTime date = DateTime.MaxValue;
82 DateTime.TryParse(adaptedRow[propertyInfo.Name].ToString(),
83 CultureInfo.CurrentCulture, DateTimeStyles.None, out date);
84
85 propertyInfo.SetValue(entity, date, null);
86 }
87 else
88 {
89 propertyInfo.SetValue(entity, adaptedRow[propertyInfo.Name], null);
90 }
91 }
92 }
以上的代码主要是针对将DataRow转换成相应的对象,方法为
(1)public static object ToEntity(DataRow adaptedRow, Type entityType)
(2)public static T ToEntity<T>(DataRow adaptedRow, T value) where T:new()
PropertyInfo[] propertyInfos = entity.GetType().GetProperties();
(二)Activator 类
对于Activator 类,主要为以下3个比较常用,包括对object和T的对象实例化。
2 {
3 public static T CreateInstance<T>();
4 public static object CreateInstance(Type type);
5 public static object CreateInstance(Type type, params object[] args);
6 }
(三)PropertyInfo的灵活运用
一般情况下,我们会对PropertyInfo进行灵活运用,以达到相应的目标,这是大家惯用的伎俩,哈哈。
先根据Type.GetProperties()获取该类型的所有属性,返回为属性数组PropertyInfo[]。
然后对PropertyInfo[] 进行相应的操作。
相应的PropertyInfo 主要有以下几个常用的方法,如下:
(四)相关的单元测试如下:
以上的2个主要方法的单元测试如下:
2 public void ToEntityTest()
3 {
4 Information information = CreateNewItem();
5
6 DataRow adaptedRow = CreateNewDataRow(information);
7 Type entityType = typeof(Information);
8 Information actual = (Information)Mapper.ToEntity(adaptedRow, entityType);
9
10 AssertInformationState(information, actual);
11 }
12
13 /// <summary>
14 ///ToEntity<T> 的测试
15 ///</summary>
16 [TestMethod()]
17 public void ToEntityGenericTest()
18 {
19 Information information = CreateNewItem();
20 DataRow adaptedRow = CreateNewDataRow(information);
21
22 Information actual = (Information)Mapper.ToEntity<Information>(adaptedRow,information);
23
24 AssertInformationState(information, actual);
25 }
26
27 private static void AssertInformationState(Information information, Information actual)
28 {
29 Assert.IsNotNull(actual);
30 Assert.IsNull(actual.Address);
31 Assert.IsNull(actual.Region);
32 Assert.AreEqual(information.Id, actual.Id);
33 Assert.AreEqual(information.Name, actual.Name);
34 Assert.AreEqual(information.CreateDate, actual.CreateDate);
35 }
36
37 private static Information CreateNewItem()
38 {
39 Information information = new Information()
40 {
41 Id = 0,
42 Name = "Jasen",
43 CreateDate = DateTime.Now,
44 Region = null
45 };
46
47 return information;
48 }
49
50 private DataRow CreateNewDataRow(Information information)
51 {
52 DataTable table= CreateTempTable();
53 DataRow row= table.NewRow();
54
55 row["Name"] = information.Name;
56 row["CreateDate"] = information.CreateDate;
57 table.Rows.Add(row);
58
59 return table.Rows[0];
60 }
61
62 private DataTable CreateTempTable()
63 {
64 DataTable namesTable = new DataTable("Temp");
65
66 DataColumn idColumn = new DataColumn();
67 idColumn.DataType = System.Type.GetType("System.Int32");
68 idColumn.ColumnName = "id";
69 idColumn.AutoIncrement = true;
70 namesTable.Columns.Add(idColumn);
71
72 DataColumn nameColumn = new DataColumn();
73 nameColumn.DataType = System.Type.GetType("System.String");
74 nameColumn.ColumnName = "Name";
75 nameColumn.DefaultValue = "Name";
76 namesTable.Columns.Add(nameColumn);
77
78 DataColumn createDateColumn = new DataColumn();
79 createDateColumn.DataType = System.Type.GetType("System.DateTime");
80 createDateColumn.ColumnName = "CreateDate";
81 namesTable.Columns.Add(createDateColumn);
82
83 DataColumn regionColumn = new DataColumn();
84 regionColumn.DataType = System.Type.GetType("System.String");
85 regionColumn.ColumnName = "Region";
86 namesTable.Columns.Add(regionColumn);
87
88 DataColumn[] keys = new DataColumn[1];
89 keys[0] = idColumn;
90 namesTable.PrimaryKey = keys;
91
92 return namesTable;
93 }
以上的2处标识红色的代码段为主要的验证逻辑,代码应该比较清晰以及简单,故本人不会讲解其中的代码。
总的来说,对于将DataRow转换成相应的对象或者泛型,主要是通过反射来进行操作的。以前也看到过很多别人写的相关类似的功能,不过很多都是不怎么好的,BUG无数.......莫名其妙的,哈哈,跟款哥混了一阵,也开始偶尔对代码眼光挑剔了,近朱者赤,近墨者黑,还真是这么一回事。以前做个什么,只要基本功能实现了,谁还去管它呢!现在代码改个几遍,依旧还是会仔细去看、去想,尽量会去考虑各种情况。
2 {
3 public static bool operator !=(PropertyInfo left, PropertyInfo right);
4 public static bool operator ==(PropertyInfo left, PropertyInfo right);
5
6 public abstract bool CanRead { get; }
7 public abstract bool CanWrite { get; }
8 public abstract Type PropertyType { get; }
9
10 public virtual object GetValue(object obj, object[] index);
11 public abstract object GetValue(object obj, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture);
12
13 public virtual void SetValue(object obj, object value, object[] index);
14 public abstract void SetValue(object obj, object value, BindingFlags invokeAttr, Binder binder, object[] index, CultureInfo culture);
15 }
还有一个比较重要的属性:public abstract string Name { get; }
以上对象相应的方法的实例和运用请参考MSDN。