/// <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开发基础知识碎片

    1:contentSize.contentInset和contentOffset区别 contentSize 是scrollview中的一个属性,它代表scrollview中的可显示区域,假如有一个s ...

  2. [bzoj1911][Apio2010]特别行动队

    Description 有个元素,可以将个元素分成多组,每组的元素编号必须是连续的. 设每组的为,则每组的价值公式为. 求最大价值和. Input 输入由三行组成. 第一行包含一个整数,表示士兵的总数 ...

  3. Android热身:通过网络获取资源并更新UI组件

    Android热身:通过网络获取资源并更新UI组件 目标 点击"发送请求"按钮,下载某网页的html源码,并显示在TextView控件上:点击"清空",清除Te ...

  4. springMVC-数据绑定流程

    1.Spring MVC主框架将ServletRequest对象以及目标方法的入参实例传递给WebDataBinderFactory实例,以创建DataBinder(数据绑定器)实例对象 2.Data ...

  5. 【poj1017】 Packets

    http://poj.org/problem?id=1017 (题目链接) 题意 一个工厂制造的产品形状都是长方体盒子,它们的高度都是 h,长和宽都相等,一共有六个型号,分别为1*1, 2*2, 3* ...

  6. Loadrunner在post请求的cookie中插入其它多个值

    有一个商城,提交订单的时候,需要在post请求的cookie中set一个code码,便于防刷 tijiao() { lr_think_time(); web_reg_save_param(" ...

  7. Some Simple Models of Neurons

    Linear neuron: \[y=b+\sum\limits_i{x_i w_i}\] Binary threshold neuron: \[z = \sum\limits_i{x_i w_i}\ ...

  8. Error=Bias+Variance

    首先 Error = Bias + Variance Error反映的是整个模型的准确度,Bias反映的是模型在样本上的输出与真实值之间的误差,即模型本身的精准度,Variance反映的是模型每一次输 ...

  9. Linux添加新盘扩容空间

    添加磁盘扩容操作:1.添加物理磁盘到服务器重启服务器,#fdisk -l查看识别磁盘(以/dev/sdb为例)[ ~]# fdisk -lDisk /dev/sda: 42.9 GB, 4294967 ...

  10. 深入JVM-java虚拟机的基本结构

    本文将介绍Java虚拟机的基本结构,各组成部分的作用,以及相互之间是如何协调的.而要了解这些,首先必须了解Java堆.Java栈.永久区和元数据区的基本概念. 一.Java虚拟机的架构 1.1 类加载 ...