zoukankan      html  css  js  c++  java
  • Expression构建DataTable to Entity 映射委托

     1 namespace Echofool.Utility.Common {
     2     using System;
     3     using System.Collections.Generic;
     4     using System.Data;
     5     using System.Linq.Expressions;
     6     using System.Reflection;
     7     using System.Reflection.Emit;
     8 
     9     public class DataTableUtility {
    10 
    11         public static IEnumerable<T> Get<T>(DataTable table) where T : new() {
    12             if (table == null) {
    13                 yield break;
    14             }
    15             if (table.Rows.Count == 0) {
    16                 yield break;
    17             }
    18             foreach (DataRow row in table.Rows) {
    19                 yield return Get<T>(row);
    20             }
    21         }
    22 
    23         public static T Get<T>(DataRow row) where T : new() {
    24             return GenericCache<T>.Factory(row);
    25         }
    26 
    27         public class GenericCache<T> where T : new() {
    28             static GenericCache() {
    29                 //Factory = GetFactoryIL(); 这里写错了
    Factory = GetFactory(); 30 } 31 public static readonly Func<DataRow, T> Factory; 32 33 private static Func<DataRow, T> GetFactory() { 34 var type = typeof(T); 35 var rowType = typeof(DataRow); 36 var rowDeclare = Expression.Parameter(rowType, "row"); 37 var instanceDeclare = Expression.Parameter(type, "instance"); 38 var newExpression = Expression.New(type); 39 var instanceExpression = Expression.Assign(instanceDeclare, newExpression); 40 var nullEqualExpression = Expression.Equal(rowDeclare, Expression.Constant(null)); 41 var containsMethod = typeof(DataColumnCollection).GetMethod("Contains"); 42 var indexerMethod = rowType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public, null, 43 new[] { typeof(string) }, 44 new[] { new ParameterModifier(1) }); 45 var setExpressions = new List<Expression>(); 46 var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); 47 var columns = Expression.Property(Expression.Property(rowDeclare, "Table"), "Columns"); 48 foreach (var propertyInfo in properties) { 49 if (propertyInfo.CanWrite) { 50 var propertyName = Expression.Constant(propertyInfo.Name, typeof(string)); 51 var checkIfContainsColumn = 52 Expression.Call(columns, containsMethod, propertyName); 53 var propertyExpression = Expression.Property(instanceDeclare, propertyInfo); 54 var value = Expression.Call(rowDeclare, indexerMethod, propertyName); 55 var proertyAssign = Expression.Assign(propertyExpression, Expression.Convert(value, propertyInfo.PropertyType)); 56 setExpressions.Add(Expression.IfThen(checkIfContainsColumn, proertyAssign)); 57 } 58 } 59 var checkIfRowIsNull = Expression.IfThenElse(nullEqualExpression, Expression.Empty(), Expression.Block(setExpressions)); 60 var body = Expression.Block(new[] { instanceDeclare }, newExpression, instanceExpression, checkIfRowIsNull, instanceDeclare); 61 return Expression.Lambda<Func<DataRow, T>>(body, rowDeclare).Compile(); 62 } 63 } 64 65 public static T GetByReflection<T>(DataRow dr) where T : new() { 66 var t = new T(); 67 if (dr != null) { 68 foreach (var p in typeof(T).GetProperties()) { 69 if (!dr.Table.Columns.Contains(p.Name)) { 70 continue; 71 } 72 var obj = dr[p.Name]; 73 var set = p.GetSetMethod(); 74 if (set == null) { 75 continue; 76 } 77 p.SetValue(t, obj, null); 78 } 79 } 80 return t; 81 } 82 } 83 }


    通过Expression动态构建DataTable映射到实体类,在三层架构中,如果使用的数据层是使用Ado.Net技术,那么加上这个DataTable to Entity的工具类,将为你减少很多代码量。

    主要目的是解决DataTable到Entity的映射关系。   

     1         public class MyClass {
     2             public MyClass() { }
     3 
     4             public MyClass(DataRow row) {
     5                 if (row != null) {
     6                     if (row.Table.Columns.Contains("Name")) {
     7                         this.Name = (string)row["Name"];
     8                     }
     9                     if (row.Table.Columns.Contains("Age")) {
    10                         this.Age = (int)row["Age"];
    11                     }
    12                 }
    13             }
    14 
    15             public string Name { get; set; }
    16             public int Age { get; set; }
    17 
    18         }

    如上定义的实体类MyClass,有一个string类型的Name属性和一个int类型的Age属性。

    如果自定义构造函数是可以很方便的从DataRow对象中获取数据填充实体类,但如果涉及的实体类太多,而且如果想通过定义特性标记 来实现一些字段特殊处理,构造函数的方式,需要你写太多的代码,而且很多都是重复的逻辑。

    现在使用DataTableUtility.Get<MyClass>.Get(row);就能很方便的获取一个实体类。

    现在使用DataTableUtility.Get<MyClass>.Get(table);就能很方便的获取一个实体类集合。

  • 相关阅读:
    Java异常之初认识二
    Java异常之初认识
    enum类型用于switch语句
    数组指定元素查找 之 二分法查找
    数组元素查找 之 线性查找
    数组的反转
    枚举类 Enum 之初认识
    求数组元素的最大值,最小值,总和,平均数
    clone()方法引发的对protected权限修饰符的思考
    完成一个朋友圈的表设计
  • 原文地址:https://www.cnblogs.com/echofool/p/expression_datatable_entity_mapping.html
Copyright © 2011-2022 走看看