namespace Echofool.Utility.Common {
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit; public class DataTableUtility { public static IEnumerable<T> Get<T>(DataTable table) where T : new() {
if (table == null) {
yield break;
}
if (table.Rows.Count == ) {
yield break;
}
foreach (DataRow row in table.Rows) {
yield return Get<T>(row);
}
} public static T Get<T>(DataRow row) where T : new() {
return GenericCache<T>.Factory(row);
} public class GenericCache<T> where T : new() {
static GenericCache() {
//Factory = GetFactoryIL(); 这里写错了
Factory = GetFactory();
}
public static readonly Func<DataRow, T> Factory; private static Func<DataRow, T> GetFactory() {
var type = typeof(T);
var rowType = typeof(DataRow);
var rowDeclare = Expression.Parameter(rowType, "row");
var instanceDeclare = Expression.Parameter(type, "instance");
var newExpression = Expression.New(type);
var instanceExpression = Expression.Assign(instanceDeclare, newExpression);
var nullEqualExpression = Expression.Equal(rowDeclare, Expression.Constant(null));
var containsMethod = typeof(DataColumnCollection).GetMethod("Contains");
var indexerMethod = rowType.GetMethod("get_Item", BindingFlags.Instance | BindingFlags.Public, null,
new[] { typeof(string) },
new[] { new ParameterModifier() });
var setExpressions = new List<Expression>();
var properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
var columns = Expression.Property(Expression.Property(rowDeclare, "Table"), "Columns");
foreach (var propertyInfo in properties) {
if (propertyInfo.CanWrite) {
var propertyName = Expression.Constant(propertyInfo.Name, typeof(string));
var checkIfContainsColumn =
Expression.Call(columns, containsMethod, propertyName);
var propertyExpression = Expression.Property(instanceDeclare, propertyInfo);
var value = Expression.Call(rowDeclare, indexerMethod, propertyName);
var proertyAssign = Expression.Assign(propertyExpression, Expression.Convert(value, propertyInfo.PropertyType));
setExpressions.Add(Expression.IfThen(checkIfContainsColumn, proertyAssign));
}
}
var checkIfRowIsNull = Expression.IfThenElse(nullEqualExpression, Expression.Empty(), Expression.Block(setExpressions));
var body = Expression.Block(new[] { instanceDeclare }, newExpression, instanceExpression, checkIfRowIsNull, instanceDeclare);
return Expression.Lambda<Func<DataRow, T>>(body, rowDeclare).Compile();
}
} public static T GetByReflection<T>(DataRow dr) where T : new() {
var t = new T();
if (dr != null) {
foreach (var p in typeof(T).GetProperties()) {
if (!dr.Table.Columns.Contains(p.Name)) {
continue;
}
var obj = dr[p.Name];
var set = p.GetSetMethod();
if (set == null) {
continue;
}
p.SetValue(t, obj, null);
}
}
return t;
}
}
}

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

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

         public class MyClass {
public MyClass() { } public MyClass(DataRow row) {
if (row != null) {
if (row.Table.Columns.Contains("Name")) {
this.Name = (string)row["Name"];
}
if (row.Table.Columns.Contains("Age")) {
this.Age = (int)row["Age"];
}
}
} public string Name { get; set; }
public int Age { get; set; } }

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

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

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

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

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

  1. Expression构建DataTable to Entity 映射委托 sqlserver 数据库里面金额类型为什么不建议用float,实例告诉你为什么不能。 sql server 多行数据合并成一列 C# 字符串大写转小写,小写转大写,数字保留,其他除外 从0开始用U盘制作启动盘装Windows10系统(联想R720笔记本)并永久激活方法 纯CSS打造淘宝导航菜单栏 C# Winform

    Expression构建DataTable to Entity 映射委托   1 namespace Echofool.Utility.Common { 2 using System; 3 using ...

  2. JDK注解替代Hibernate的Entity映射

    1.在entity(实体类)模块中使用注解 1_1.注解的位置出现在 [类定义的前面] 和 [属性的get方法前面] [属性的get方法前面] Java代码: package app.entity; ...

  3. Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串

    原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...

  4. 数据库查询 - DataTable转Entity类型数据

    当使用Sql语句查询数据库,返回DataSet数据集. DataSet转化为数据列表,可以通过映射方式直接返回Entity数据列表 新建一个特性类,用于数据库列表列名称映射 LinqToDB提供了一个 ...

  5. DataTable转Entity(Emit版)

    public static List<T> ToList<T>(DataTable dt)        {            List<T> list = n ...

  6. C#构建DataTable(转)

    Asp.net DataTable添加列和行的方法 方法一: DataTable tblDatas = new DataTable("Datas"); DataColumn dc ...

  7. List转换为DataTable List<Entity>

    /// <summary> /// 将List转换成DataTable /// </summary> /// <typeparam name="T"& ...

  8. DataTable To Entity

    using System;using System.Collections.Generic;using System.Data;using System.Reflection;using System ...

  9. .net core mysql entity映射时字符串被截断

    参考地址:https://stackoverflow.com/questions/40833262/net-core-entity-framework-mysql-string-fields-stor ...

随机推荐

  1. elasticsearch 重启后,需要的操作

    如果elasticsearch 集群挂了,请勿开启Logstash 同步数据,需等待elasticsearch集群恢复后,在继续写入

  2. C++中输出流运算符的重载

    cout是ostream类的对象,cin是istream类的对象. 我们平时用的cout<<就相当于cout.operator<<(...).也就是说正常使用(不对operat ...

  3. 如何修改Oracle用户密码

    大家如果不知道oracle数据库的密码的话,我们可以通过简单的命令行把密码进行修改. 1.打开cmd 2 在弹出的命令提示窗口输入 set oracle_sid=数据库名称(实例),回车.例如数据库名 ...

  4. 金错刀对话口袋购物王珂:找到痛点,确认卖点,制造爆点! - 资讯 - i黑马网

    金错刀对话口袋购物王珂:找到痛点,确认卖点,制造爆点! - 资讯 - i黑马网 金错刀对话口袋购物王珂:找到痛点,确认卖点,制造爆点!

  5. Linux红黑树(一)——数据结构

    摘要 兹博文探讨四个重点:1.简单介绍红黑树:2.红黑树节点数据结构:3.红黑树节点中父节点指针域和自身节点颜色有机结合:4.定义红黑树和操作树节点父节点指针和节点颜色的接口,包括一系列宏和两个函数. ...

  6. Welcome to Apache™ Hadoop®!

    What Is Apache Hadoop? Getting Started Download Hadoop Who Uses Hadoop? News 15 October, 2013: relea ...

  7. [Angular 2] *ngFor with index

    Let's see how to track index when we use 'ngFor: <li *ngFor="#hero of heros | async, #i = in ...

  8. SharePoint 要一个多行文本类型字段为特殊类型的链接

    1.插入在测试列表中的多行文本字段.名字叫做Content.例如下面的附图: 2.在Content字段里.加入一个Link.例如以下图: 3.尝试输入Notes格式的Link,例如以下图: 4.点击O ...

  9. MAVEN Scope使用

    在Maven的依赖管理中,经常会用到依赖的scope设置.这里整理下各种scope的使用场景和说明,以及在使用中的实践心得.Scope的使用场景和说明1.compile编译范围,默认scope,在工程 ...

  10. hdu 2033

    水题 AC代码: #include <iostream> using namespace std; int main() { int i,j,n,k,a[100],b[100]; cin& ...