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. OpenLayers 3 之 地图样式(ol.style)详解

    地图样式是由 style 类控制的,其包含了地图样式的方方面面,例如,填充色.图标样式.图片样式.规则图形样式.边界样式.文字样式等,样式一般针对矢量要素图层. 矢量图层样式可以事先写好,写成静态的, ...

  2. ASP.NET探讨:技术的学习顺序问题

    作者: シtearシ  来源: 博客园  发布时间: 2011-09-27 08:40  阅读: 7675 次  推荐: 25   原文链接   [收藏]   摘要:很多人对于ASP.NET的入门和学 ...

  3. Redis——学习之路二(初识redis服务器命令)

    上一章我们已经知道了如果启动redis服务器,现在我们来学习一下,以及如何用客户端连接服务器.接下来我们来学习一下查看操作服务器的命令. 服务器命令: 1.info——当前redis服务器信息   s ...

  4. Redis为什么使用单进程单线程方式也这么快

    [转] http://www.syyong.com/db/Redis-why-the-use-of-single-process-and-single-threaded-way-so-fast.htm ...

  5. ViewPager+Fragment取消预加载(延迟加载)(转)

    原文:http://www.2cto.com/kf/201501/368954.html 在项目中,都或多或少地使用的Tab布局,所以大都会用到ViewPager+Fragment,但是Fragmen ...

  6. C# 发送邮件中包含图片

    List<string> To = new List<string>(); To.Add("jake_ge@askey.com.tw"); List< ...

  7. Code Lock[HDU3461]

    Code LockTime Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Subm ...

  8. 【BZOJ】4002: [JLOI2015]有意义的字符串

    题意 求$\left \lfloor \left( \frac{b+\sqrt{d}}{2} \right)^n \right \rfloor \pmod {7528443412579576937} ...

  9. Android -- PopupWindow(其中嵌套ListView 可以被点击)

    1. 效果图

  10. BZOJ4455: [Zjoi2016]小星星

    Description 小Y是一个心灵手巧的女孩子,她喜欢手工制作一些小饰品.她有n颗小星星,用m条彩色的细线串了起来,每条细 线连着两颗小星星.有一天她发现,她的饰品被破坏了,很多细线都被拆掉了.这 ...