将DataRow转换成相应的对象(通用以及泛型操作)

  一直以来对框架非常感兴趣,对大多数框架(目前本人看过的)来说一般分为三个部分:

(1):拼接SQL语句(反射)。

(2):执行CRUD操作,获取相应的DataTable、DataSet等等。

(3):将相应的DataTable、DataSet转换成对象(反射)。

因此可以将上述3个部分各个击破,一步一步来实现自己的框架,看的框架多了,也就成了路。反射在这里面被淋漓尽致的运用,哈哈,站在款哥的肩膀上......

 

(一)通用以及泛型转换代码

先看下面关于将DataRow转换成相应的对象(通用以及泛型操作)的方法(这里仅仅是对DataRow进行转换,对于将DataTable转换成对象集合,思路基本差不多,因此本例里不再对其他的进行相关代码的编写):

 1      public   class  Mapper
 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()

 

(二)Activator 类

对于Activator 类,主要为以下3个比较常用,包括对object和T的对象实例化。

1          public   sealed   class  Activator : _Activator
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[] propertyInfos = entity.GetType().GetProperties();

然后对PropertyInfo[] 进行相应的操作。

 

相应的PropertyInfo 主要有以下几个常用的方法,如下:

 1       public   abstract   class  PropertyInfo : MemberInfo, _PropertyInfo
 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。

(四)相关的单元测试如下:

以上的2个主要方法的单元测试如下:

 1          [TestMethod()]
 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无数.......莫名其妙的,哈哈,跟款哥混了一阵,也开始偶尔对代码眼光挑剔了,近朱者赤,近墨者黑,还真是这么一回事。以前做个什么,只要基本功能实现了,谁还去管它呢!现在代码改个几遍,依旧还是会仔细去看、去想,尽量会去考虑各种情况。现在发现自己变了,哈哈.....

 

源代码下载:DataRow转换成对象源代码下载

 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值