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. Codeforces Round #388 (Div. 2) - C

    题目链接:http://codeforces.com/contest/749/problem/C 题意:给定一个长度为n的D/R序列,代表每个人的派别,然后进行发表意见,顺序是从1到n.每个人到他的回 ...

  2. PDA无线数据采集器在仓库管理系统中的应用

    条码数据采集器在仓库管理系统中的应用,条码数据采集器,顾名思义就是通过扫描货物条码,对货物进行数量分类采集,方便仓库正规化管理.条码数据采集器是现代化条码仓库管理系统中不可缺少的一部分,能提升企业的整 ...

  3. LeetCode 412. Fizz Buzz

    Problem: Write a program that outputs the string representation of numbers from 1 to n. But for mult ...

  4. AutoCAD 2007-2012 长度统计工具

    长度统计工具 下载 1 解压到磁盘 2 CAD 中输入命令 netload 3 选择文件 "CADLittleProgram.dll" 4 点击 Ps:后续会打包并支持2013-2 ...

  5. [转]webpack

    什么是 webpack? webpack是近期最火的一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX).coffee.样式(含less/sass).图片等都作为模块来使用和处理. 我们可以 ...

  6. Arduino下LCD1602综合探究(上)——1602的两种驱动方式,如何使LCD的控制编程变得更简单

    一.前言: LCD ( Liquid Crystal Display 的简称)液晶显示器,已经逐渐替代CRT成为主流的显示设备之一,因此也成为了单片机发烧友绕不过的话题之一:而LCD1602更是很多单 ...

  7. [Noip2016]蚯蚓 D2 T2 队列

    [Noip2016]蚯蚓 D2 T2 Description 本题中,我们将用符号[c]表示对c向下取整,例如:[3.0」= [3.1」=[3.9」=3.蛐蛐国最近蚯蚓成灾了!隔壁跳 蚤国的跳蚤也拿蚯 ...

  8. 数论 - Moon Game

    Fat brother and Maze are playing a kind of special (hentai) game in the clearly blue sky which we ca ...

  9. Web API Get Started First

    注:此博客是自官网修剪而来,博主IT新手 一.web api与web service的不同: web api是基于Http协议,而web service是基于soap协议.两协议的区别小子看了很多,但 ...

  10. oracle遍历表更新另一个表(一对多)

    declare cursor cur_test is select t.txt_desig, m.segment_id, s.code_type_direct, case when s.uom_dis ...