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);就能很方便的获取一个实体类集合。

Expression构建DataTable to Entity 映射委托

时间: 2024-08-04 17:23:31

Expression构建DataTable to Entity 映射委托的相关文章

JDK注解替代Hibernate的Entity映射

1.在entity(实体类)模块中使用注解 1_1.注解的位置出现在 [类定义的前面] 和 [属性的get方法前面] Java代码: package app.entity; //模型 //注意看,导入的是jdk的拓展包 import javax.persistence.*; @Entity //告诉Spring这个类是实体类.模型类 @Table(name="t_demo") //声明这个模型对于其哪张数据表 public class Demo { private Integer ci

构建DataTable

[博客原因]数据一直来自于数据库,造成本地构建Datatable 当做数据源不会了,特此记录一下 DataTable dt = new DataTable(); //构建列 dt.Columns.Add(new DataColumn("id")); dt.Columns.Add(new DataColumn("ServerID")); dt.Columns.Add(new DataColumn("SN")); dt.Columns.Add(new

DataTable转换为Entity(反射&amp;&amp;泛型)

public static IEnumerable<T> Parse<T>(IEnumerable<DataRow> rows) where T : class, new() { if (rows == null || Enumerable.FirstOrDefault<DataRow>(rows) == null) return (IEnumerable<T>) new T[0]; PropertyInfo[] properties = typ

Gradle 庖丁解牛(构建生命周期核心委托对象创建源码浅析)

[工匠若水 http://blog.csdn.net/yanbober 未经允许严禁转载,请尊重作者劳动成果.私信联系我] 1 背景 上一篇<Gradle 庖丁解牛(构建源头源码浅析)>我们分析了 Gradle 框架自身初始化(非构建生命周期初始化)的核心流程,这一篇我们续着前面的分析继续(如果没看过前一篇的建议先去看前一篇,因为这一系列存在非常高的关联性).上一篇说到当我们执行 gradle taskName 命令后经过一系列艰难的框架初始化最终走到了 DefaultGradleLaunch

Apache OFbiz entity engine源代码解读

简单介绍 近期一直在看Apache OFbiz entity engine的源代码.为了能够更透彻得理解,也由于之前没有看人别人写过分析它的文章,所以决定自己来写一篇. 首先,我提出一个问题,假设你有兴趣能够想一下它的答案: JDBC真的给数据訪问提供了足够的抽象,以至于你能够在多个支持jdbc訪问的数据库之间随意切换而全然不须要操心你的数据訪问代码吗? 我以前在微博上有过关于该问题的思考: 事实上这个感慨正是来自于我之前在看的一篇关于jdbc的文章,里面提到了jdbc中的一些设计模式(工厂方法

Entity Framework 4.1 之二 : 覆盖默认的约定

原文名称:Entity Framework 4.1: Override conventions (2) 原文地址: http://vincentlauzon.wordpress.com/2011/04/06/entity-framework-4-1-override-conventions-2/ 看到 Entity Framework 4.1 推荐英文教程,为了帮大家看起来方便一些,简单翻译一下.这是一个系列,共有 8 篇,这是第 2 篇. Entity Framework 4.1 之一 : 基

[Android Pro] AndroidX重构和映射

原文地址:https://developer.android.com/topic/libraries/support-library/refactor https://blog.csdn.net/chen_xi_hao/article/details/81741486 AndroidX重构 未与Android操作系统捆绑在一起的API包将被重构到新的androidx命名空间中.只有包名和Maven工件名受到影响; 原来的类名,方法名和字段名不会更改.有关AndroidX重构的更多信息,请参阅博客

Excel转Datatable

using NPOI.HSSF.UserModel; using NPOI.SS.UserModel; using NPOI.XSSF.UserModel; using System; using System.Collections.Generic; using System.Data; using System.Globalization; using System.IO; using System.Linq; using System.Threading; using System.Web

Hibernate关系映射(注解)

1.类级别注解 @Entity     映射实体类 @Table    映射数句库表 @Entity(name="tableName") - 必须,注解将一个类声明为一个实体bean. 属性: name - 可选,对应数据库中的一个表.若表名与实体类名相同,则可以省略. @Table(name="",catalog="",schema="")  - 可选,通常和@Entity 配合使用,只能标注在实  体的 class定义处,