public static List<T> ToList<T>(DataTable dt)
        {
            List<T> list = new List<T>();
            if (dt == null) return list;
            DataTableEntityBuilder<T> eblist = DataTableEntityBuilder<T>.CreateBuilder(dt.Rows[0]);
            foreach (DataRow info in dt.Rows)
                list.Add(eblist.Build(info));
            dt.Dispose();
            dt = null;
            return list;
        }

public class DataTableEntityBuilder<T>
        {
           
private static readonly MethodInfo getValueMethod =
typeof(DataRow).GetMethod("get_Item", new Type[] { typeof(int) });
           
private static readonly MethodInfo isDBNullMethod =
typeof(DataRow).GetMethod("IsNull", new Type[] { typeof(int) });
            private delegate T Load(DataRow dataRecord);

private Load handler;
            private DataTableEntityBuilder() { }

public T Build(DataRow dataRecord)
            {
                return handler(dataRecord);
            }

public static DataTableEntityBuilder<T> CreateBuilder(DataRow dataRow)
            {
                DataTableEntityBuilder<T> dynamicBuilder = new DataTableEntityBuilder<T>();
               
DynamicMethod method = new DynamicMethod("DynamicCreateEntity",
typeof(T), new Type[] { typeof(DataRow) }, typeof(T), true);
                ILGenerator generator = method.GetILGenerator();
                LocalBuilder result = generator.DeclareLocal(typeof(T));
                generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
                generator.Emit(OpCodes.Stloc, result);

for (int index = 0; index < dataRow.ItemArray.Length; index++)
                {
                    PropertyInfo propertyInfo = typeof(T).GetProperty(dataRow.Table.Columns[index].ColumnName);
                    Label endIfLabel = generator.DefineLabel();
                    if (propertyInfo != null && propertyInfo.GetSetMethod() != null)
                    {
                        generator.Emit(OpCodes.Ldarg_0);
                        generator.Emit(OpCodes.Ldc_I4, index);
                        generator.Emit(OpCodes.Callvirt, isDBNullMethod);
                        generator.Emit(OpCodes.Brtrue, endIfLabel);
                        generator.Emit(OpCodes.Ldloc, result);
                        generator.Emit(OpCodes.Ldarg_0);
                        generator.Emit(OpCodes.Ldc_I4, index);
                        generator.Emit(OpCodes.Callvirt, getValueMethod);
                        generator.Emit(OpCodes.Unbox_Any, propertyInfo.PropertyType);
                        generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod());
                        generator.MarkLabel(endIfLabel);
                    }
                }
                generator.Emit(OpCodes.Ldloc, result);
                generator.Emit(OpCodes.Ret);
                dynamicBuilder.handler = (Load)method.CreateDelegate(typeof(Load));
                return dynamicBuilder;
            }
        }

using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;
using System.Reflection.Emit;
using System.Web.Caching;
using System.Web;
 
namespace LinFramework
{
    /// <summary>
    /// 实体转换
    /// </summary>
    public class EntityConverter
    {
        //数据类型和对应的强制转换方法的methodinfo,供实体属性赋值时调用
        private static Dictionary<Type, MethodInfo> ConvertMethods = new Dictionary<Type, MethodInfo>()
       {      
           {typeof(int),typeof(Convert).GetMethod("ToInt32",new Type[]{typeof(object)})}, 
           {typeof(Int16),typeof(Convert).GetMethod("ToInt16",new Type[]{typeof(object)})}, 
           {typeof(Int64),typeof(Convert).GetMethod("ToInt64",new Type[]{typeof(object)})}, 
           {typeof(DateTime),typeof(Convert).GetMethod("ToDateTime",new Type[]{typeof(object)})}, 
           {typeof(decimal),typeof(Convert).GetMethod("ToDecimal",new Type[]{typeof(object)})}, 
           {typeof(Double),typeof(Convert).GetMethod("ToDouble",new Type[]{typeof(object)})},
           {typeof(Boolean),typeof(Convert).GetMethod("ToBoolean",new Type[]{typeof(object)})},
           {typeof(string),typeof(Convert).GetMethod("ToString",new Type[]{typeof(object)})}      
       };
 
        //把datarow转换为实体的方法的委托定义
        public delegate T LoadDataRow<T>(DataRow dr);
        //把datareader转换为实体的方法的委托定义
        public delegate T LoadDataRecord<T>(IDataRecord dr);
 
        //emit里面用到的针对datarow的元数据信息
        private static readonly AssembleInfo dataRowAssembly = new AssembleInfo(typeof(DataRow));
        //emit里面用到的针对datareader的元数据信息
        private static readonly AssembleInfo dataRecordAssembly = new AssembleInfo(typeof(IDataRecord));
 
        /// <summary>
        /// 构造转换动态方法(核心代码),根据assembly可处理datarow和datareader两种转换
        /// </summary>
        /// <typeparam name="T">返回的实体类型</typeparam>
        /// <param name="assembly">待转换数据的元数据信息</param>
        /// <returns>实体对象</returns>
        private static DynamicMethod BuildMethod<T>(AssembleInfo assembly)
        {
            DynamicMethod method = new DynamicMethod(assembly.MethodName + typeof(T).Name, MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, typeof(T),
                    new Type[] { assembly.SourceType }, typeof(EntityContext).Module, true);
            ILGenerator generator = method.GetILGenerator();
            LocalBuilder result = generator.DeclareLocal(typeof(T));
            generator.Emit(OpCodes.Newobj, typeof(T).GetConstructor(Type.EmptyTypes));
            generator.Emit(OpCodes.Stloc, result);
 
            foreach (PropertyInfo property in typeof(T).GetProperties())
            {
                Label endIfLabel = generator.DefineLabel();
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldstr, property.Name);
                generator.Emit(OpCodes.Callvirt, assembly.CanSettedMethod);
                generator.Emit(OpCodes.Brfalse, endIfLabel);
                generator.Emit(OpCodes.Ldloc, result);
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldstr, property.Name);
                generator.Emit(OpCodes.Callvirt, assembly.GetValueMethod);
                if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
                    generator.Emit(OpCodes.Call, ConvertMethods[property.PropertyType]);
                else
                    generator.Emit(OpCodes.Castclass, property.PropertyType);
                generator.Emit(OpCodes.Callvirt, property.GetSetMethod());
                generator.MarkLabel(endIfLabel);
            }
            generator.Emit(OpCodes.Ldloc, result);
            generator.Emit(OpCodes.Ret);
            return method;
        }
 
        /// <summary>
        /// 从Cache获取委托 LoadDataRow<T>的方法实例,没有则调用BuildMethod构造一个。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private static LoadDataRow<T> GetDataRowMethod<T>()
        {
            string key = dataRowAssembly.MethodName + typeof(T).Name;
            LoadDataRow<T> load = null;
            if (HttpRuntime.Cache[key] == null)
            {
                load = (LoadDataRow<T>)BuildMethod<T>(dataRowAssembly).CreateDelegate(typeof(LoadDataRow<T>));
                HttpRuntime.Cache[key] = load;
            }
            else
            {
                load = HttpRuntime.Cache[key] as LoadDataRow<T>;
            }
            return load;
        }
 
        /// <summary>
        /// 从Cache获取委托 LoadDataRecord<T>的方法实例,没有则调用BuildMethod构造一个。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        private static LoadDataRecord<T> GetDataRecordMethod<T>()
        {
            string key = dataRecordAssembly.MethodName + typeof(T).Name;
            LoadDataRecord<T> load = null;
            if (HttpRuntime.Cache[key] == null)
            {
                load = (LoadDataRecord<T>)BuildMethod<T>(dataRecordAssembly).CreateDelegate(typeof(LoadDataRecord<T>));
                HttpRuntime.Cache[key] = load;
            }
            else
            {
                load = HttpRuntime.Cache[key] as LoadDataRecord<T>;
            }
            return load;
        }
 
 
        public static T ToItem<T>(DataRow dr)
        {
            LoadDataRow<T> load = GetDataRowMethod<T>();
            return load(dr);
        }
 
        public static List<T> ToList<T>(DataTable dt)
        {
            List<T> list = new List<T>();
            if (dt == null || dt.Rows.Count == 0)
            {
                return list;
            }
            LoadDataRow<T> load = GetDataRowMethod<T>();
            foreach (DataRow dr in dt.Rows)
            {
                list.Add(load(dr));
            }
            return list;
        }
 
        public static List<T> ToList<T>(IDataReader dr)
        {
            List<T> list = new List<T>();
            LoadDataRecord<T> load = GetDataRecordMethod<T>();
            while (dr.Read())
            {
                list.Add(load(dr));
            }
            return list;
        }
 
    }
 
    /// <summary>
    /// emit所需要的元数据信息
    /// </summary>
    public class AssembleInfo
    {
        public AssembleInfo(Type type)
        {
            SourceType = type;
            MethodName = "Convert" + type.Name + "To";
            CanSettedMethod = this.GetType().GetMethod("CanSetted", new Type[] { type, typeof(string) });
            GetValueMethod = type.GetMethod("get_Item", new Type[] { typeof(string) });
        }
        public string MethodName;
        public Type SourceType;
        public MethodInfo CanSettedMethod;
        public MethodInfo GetValueMethod;
 
        /// <summary>
        /// 判断datareader是否存在某字段并且值不为空
        /// </summary>
        /// <param name="dr">当前的datareader</param>
        /// <param name="name">字段名</param>
        /// <returns></returns>
        public static bool CanSetted(IDataRecord dr, string name)
        {
            bool result = false;
            for (int i = 0; i < dr.FieldCount; i++)
            {
                if (dr.GetName(i).Equals(name, StringComparison.CurrentCultureIgnoreCase) && !dr[i].Equals(DBNull.Value))
                {
                    result = true;
                    break;
                }
            }
            return result;
        }
 
        /// <summary>
        /// 判断datarow所在的datatable是否存在某列并且值不为空
        /// </summary>
        /// <param name="dr">当前datarow</param>
        /// <param name="name">字段名</param>
        /// <returns></returns>
        public static bool CanSetted(DataRow dr, string name)
        {
            return dr.Table.Columns.Contains(name) && !dr.IsNull(name);
        }
    }
}
 
 
 
四、如何使用
 
使用起来就很简单了
 
 
 
List<E> list = EntityConverter.ToList<E>(dr);
 
... 
 
List<E> list = EntityConverter.ToList<E>(dt);
 
 
 
当然,利用泛型还可以再进一步封装,
 
 
      public  List<TEntity> QueryBySQL<TEntity>(string sql)
        {
           
            using (IDataReader dr = sqlCommand.ExecuteReader(sql)
            {
                return EntityConverter.ToList<TEntity>(dr);
            }
 
        }

DataTable转Entity(Emit版)的更多相关文章

  1. Expression构建DataTable to Entity 映射委托

    namespace Echofool.Utility.Common { using System; using System.Collections.Generic; using System.Dat ...

  2. 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 ...

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

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

  4. c#将List转换成DataTable(采用Emit)

    前段时间通过网上查找,使用emit将Datatable,DataReader转换成List<T>了.这是从数据库到展示. 但是最近整理Hikari(我写的数据库连接池),发现c#里面数据库 ...

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

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

  6. 动态多条件查询分页以及排序(一)--MVC与Entity Framework版url分页版

    一.前言 多条件查询分页以及排序  每个系统里都会有这个的代码 做好这块 可以大大提高开发效率  所以博主分享下自己的6个版本的 多条件查询分页以及排序 二.目前状况 不论是ado.net 还是EF ...

  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. DataTable转换为Entity(反射&&泛型)

    public static IEnumerable<T> Parse<T>(IEnumerable<DataRow> rows) where T : class, ...

随机推荐

  1. 【iOS自定义键盘及键盘切换】详解

    [iOS自定义键盘]详解 实现效果展示: 一.实现的协议方法代码 #import <UIKit/UIKit.h> //创建自定义键盘协议 @protocol XFG_KeyBoardDel ...

  2. 什么是Angularjs

    AngularJs(后面就简称ng了)是一个用于设计动态web应用的结构框架.首先,它是一个框架,不是类库,是像EXT一样提供一整套方案用于设计web应用.它不仅仅是一个javascript框架,因为 ...

  3. 转:简单窗体振动-WaitForSingleObject,消息,winapi

    http://www.cnblogs.com/Jekhn/archive/2012/08/25/2656656.html 线程,消息函数,SetWindowPos设置窗体位置 if WaitForSi ...

  4. C++ win32线程数上限

    hThread = CreateThread( NULL,  0,  WorkerFunction,  &threadParm,  0, &dwThreadID  ); 这样的创建方法 ...

  5. 三星首次更新Gear VR虚拟现实浏览器Samsung Internet

    通过VR浏览网页不是问题,不过你需要一个专门的VR浏览器,而GearVR的虚拟现实应用名为"Samsung Internet for Gear VR".继去年12月份上线后,迎来了 ...

  6. Android SDK Manager 更新代理配置

    转自:http://www.cnblogs.com/tao560532/p/4483067.html 出现问题: 消除SDK更新时,有可能会出现这样的错误:Download interrupted: ...

  7. PHPer不能不看的50个细节!

    1.用单引号代替双引号来包含字符串,这样做会更快一些.因为PHP会在双引号包围的字符串中搜寻变量, 单引号则不会,注意:只有echo能这么做,它是一种可以把多个字符串当作参数的"函数&quo ...

  8. ASP.NET下回车键的触发效果

    在ASP.NET下,在客户端触发回车键,默认调用了页面中第一个button,这有时是非常头痛的,比如页面的第一个按键是注销键时,想想也够可怕了. .net提供设置默认回车键的属性,this.Form. ...

  9. C语言系统时间读取

    1 读出系统时间(每隔一秒)#include#includeint main(){  while(1) {    time_t t;    t= time(0); struct tm *p;     ...

  10. angularjs provider 供应商服务

    今天学习了angularjs的provider的供应商服务,写了个例子(自定义供应商服务,也可使用angularjs内部提供的服务) var starterApp = angular.module(' ...