/// <summary>
/// 使用Emit动态代理收集实体信息
/// </summary>
/// <typeparam name="T">实体类</typeparam>
public class TDynamicBuilder<T>
{
#region 变量区域
private static readonly MethodInfo getValueMethod = typeof(IDataRecord).GetMethod("get_Item", new[] { typeof(int) }); private static readonly MethodInfo isDBNullMethod = typeof(IDataRecord).GetMethod("IsDBNull", new[] { typeof(int) }); private delegate T Load(IDataRecord dataRecord); /// <summary>
/// 代理
/// </summary>
private Load Handler;//最终执行动态方法的一个委托 参数是IDataRecord接口
#endregion #region 构造函数
private TDynamicBuilder() { }
#endregion #region +Build Emit动态代理生成一个实体对象
/// <summary>
/// Emit动态代理生成一个实体对象
/// </summary>
/// <param name="dataRecord">DataReader接口实现对象</param>
/// <returns></returns>
public T Build(IDataRecord dataRecord)
{
return Handler(dataRecord);//执行CreateBuilder里创建的DynamicCreate动态方法的委托
}
#endregion #region + CreateBuilder 创建一个Builder器
/// <summary>
/// 创建一个Builder器
/// </summary>
/// <param name="dataRecord">DataReader接口实现对象</param>
/// <returns></returns>
public static TDynamicBuilder<T> CreateBuilder(IDataRecord dataRecord)
{
var dynamicBuilder = new TDynamicBuilder<T>();
var type = typeof(T);
//定义一个名为DynamicCreate的动态方法,返回值typof(T),参数typeof(IDataRecord)
var method = new DynamicMethod("DynamicCreate", type, new[] { typeof(IDataRecord) }, typeof(T), true);
var generator = method.GetILGenerator();//创建一个MSIL生成器,为动态方法生成代码
var result = generator.DeclareLocal(type);//声明指定类型的局部变量 可以T t;这么理解
//The next piece of code instantiates the requested type of object and stores it in the local variable. 可以t=new T();这么理解
generator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
generator.Emit(OpCodes.Stloc, result);
var propertys = type.GetProperties();
//数据集合
for (var i = ; i < dataRecord.FieldCount; i++)
{
//查找属性
var propertyInfo = propertys.FirstOrDefault(a => string.Equals(a.Name.ToLower(), dataRecord.GetName(i).ToLower()));
if (propertyInfo == null) continue;
if (!string.Equals(propertyInfo.Name, dataRecord.GetName(i), StringComparison.CurrentCultureIgnoreCase)) continue;
//根据列名取属性 原则上属性和列是一一对应的关系
var endIfLabel = generator.DefineLabel(); /*The code then loops through the fields in the data reader, finding matching properties on the type passed in.
* When a match is found, the code checks to see if the value from the data reader is null.
*/
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
//就知道这里要调用IsDBNull方法 如果IsDBNull==true contine
generator.Emit(OpCodes.Callvirt, isDBNullMethod);
generator.Emit(OpCodes.Brtrue, endIfLabel); /*If the value in the data reader is not null, the code sets the value on the object.*/
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ldarg_0);
generator.Emit(OpCodes.Ldc_I4, i);
generator.Emit(OpCodes.Callvirt, getValueMethod); //调用get_Item方法
generator.Emit(OpCodes.Unbox_Any, dataRecord.GetFieldType(i));
generator.Emit(OpCodes.Callvirt, propertyInfo.GetSetMethod()); //给该属性设置对应值 generator.MarkLabel(endIfLabel); } /*The last part of the code returns the value of the local variable*/
generator.Emit(OpCodes.Ldloc, result);
generator.Emit(OpCodes.Ret);//方法结束,返回 //完成动态方法的创建,并且创建执行该动态方法的委托,赋值到全局变量handler,handler在Build方法里Invoke
dynamicBuilder.Handler = (Load)method.CreateDelegate(typeof(Load));
return dynamicBuilder;
}
#endregion }

C# Emit动态代理生成一个实体对象的更多相关文章

  1. Java动态代理:一个面包店的动态代理帝国

    文章首发于[博客园-陈树义],点击跳转到原文大白话说Java动态代理:一个面包店的动态代理帝国 代理模式是设计模式中非常重要的一种类型,而设计模式又是编程中非常重要的知识点,特别是在业务系统的重构中, ...

  2. Emit动态代理.NetCore迁移之旅

    [前言] 前面我们介绍了Aop 从静态代理到动态代理:https://www.cnblogs.com/7tiny/p/9657451.html 我们在.NetFramework平台下使用微软提供的Em ...

  3. 通过模拟Mybatis动态代理生成Mapper代理类,讲解Mybatis核心原理

    本文将通过模拟Mybatis动态代理生成Mapper代理类,讲解Mybatis原理 1.平常我们是如何使用Mapper的 先写一个简单的UserMapper,它包含一个全表查询的方法,代码如下 pub ...

  4. 获取动态代理生成的.class文件

    生成代理类,并写入硬盘:配置系统属性sun.misc.ProxyGenerator.saveGeneratedFile为true,代理类生成时将自动将生成的代理类写入硬盘 ? 1 2 3 4 5 6 ...

  5. 【SpringCloud原理】万字剖析OpenFeign之FeignClient动态代理生成源码

    年前的时候我发布两篇关于nacos源码的文章,一篇是聊一聊nacos是如何进行服务注册的,另一篇是一文带你看懂nacos是如何整合springcloud -- 注册中心篇.今天就继续接着剖析Sprin ...

  6. JAVA-获取 JDK 动态代理生成的 Class 文件

    可指定路径 import sun.misc.ProxyGenerator; import java.io.FileOutputStream; import java.io.IOException; i ...

  7. 使用Netty和动态代理实现一个简单的RPC

    RPC(remote procedure call)远程过程调用 RPC是为了在分布式应用中,两台主机的Java进程进行通信,当A主机调用B主机的方法时,过程简洁,就像是调用自己进程里的方法一样.RP ...

  8. 做一些Spring AOP做过的事,封装 jdk动态代理成为一个黑盒子

      怎么使用eclise 抽取方法,请看  利用eclipse 抽取代码片段为方法   抽取完成之后,还需要 ① 将Collection.class换成  target.getClass(),targ ...

  9. console.log的一个应用 -----用new方法生成一个img对象和document.createElement方法创建一个img对象的区别

    我用两种方法来生成img对象,第一种方法是用new方法,第二种方法是用document.createElement方法. var img1 = new Image(); var img2 = docu ...

随机推荐

  1. iOS开发网络篇—监测网络状态(转)

    文章转载自:http://www.cnblogs.com/wendingding/p/3950114.html iOS开发网络篇—监测网络状态 一.说明 在网络应用中,需要对用户设备的网络状态进行实时 ...

  2. win10下安装Ubuntu出现win10无法进入的情况

    昨天晚上在win10上安装Ubuntu Kylin16.04系统,结果发现重启的时候进不去windows系统了,而且报的错误是 /EndEntire file path: /ACPI(a0341d,0 ...

  3. 【faster-rcnn】训练自己的数据——修改图片格式、类别

    修改图片格式 matlab代码 其实内部一些代码是用了rbg的fast-rcnn代码的. \datasets\VOCdevkit2007\VOCcode\VOCinit.m里面,查找'jpg',改成' ...

  4. win10前面板耳机没声音

    首先去装Relteck的驱动,windows64位的下载地址是: http://12244.wpc.azureedge.net/8012244/drivers/rtdrivers/pc/audio/0 ...

  5. choorme 升级到最新版 adobe flash提示过期解决方案

    进入adobe flash 官网,下载最新版的adobe flash http://labs.adobe.com/downloads/flashplayer.html

  6. [NOIP2014] 提高组 洛谷P1328 生活大爆炸版石头剪刀布

    题目描述 石头剪刀布是常见的猜拳游戏:石头胜剪刀,剪刀胜布,布胜石头.如果两个人出拳一样,则不分胜负.在<生活大爆炸>第二季第8 集中出现了一种石头剪刀布的升级版游戏. 升级版游戏在传统的 ...

  7. Linux Default Bootup、Startup、Autoload Configuration file(自启动服务脚本)

    目录 . Linux初始化init系统 . Linux配置文件自动加载过程 1. Linux初始化init系统 Linux初始化init系统在不同操作系统系列下的区别 . RHEL : SysVini ...

  8. shell命令rm删除非空文件夹

    rm -rf dirName CentOS的自带的资源管理器叫nautilus,在命令行里输入nautilus可以启动它.

  9. Oracle 数据类型

    类型 含义 CHAR(length) 存储固定长度的字符串.参数length指定了长度,如果存储的字符串长度小于length,用空格填充.默认长度是1,最长不超过2000字节. VARCHAR2(le ...

  10. Appium for IOS testing on Mac

    一:环境 1.Mac OS X 10.9.1 2.Xcod 5.0.2 3.Appium 1.3.6 下载地址:https://bitbucket.org/appium/appium.app/down ...