zoukankan      html  css  js  c++  java
  • 将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, nullnull);
    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转换成对象源代码下载

     
  • 相关阅读:
    C++中的private/protected/public
    volatile关键字和mutable关键字
    vector容器使用和assert断言关键字
    静态变量static和extern外引用
    VS开发入门常识
    电子钱包的消费——java card开发第五篇
    电子钱包的圈存——java card开发第四篇
    PPT2010制作图片玻璃磨砂效果
    Word2010制作个人名片
    Word2010制作自动目录
  • 原文地址:https://www.cnblogs.com/jasenkin/p/datarow_to_entity_or_generic_type.html
Copyright © 2011-2022 走看看