/// <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. Java并发和多线程(一)基础知识

    1.java线程状态 Java中的线程可以处于下列状态之一: NEW: 至今尚未启动的线程处于这种状态. RUNNABLE: 正在 Java 虚拟机中执行的线程处于这种状态. BLOCKED: 受阻塞 ...

  2. Leetcode 98. Validate Binary Search Tree

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...

  3. 【caffe】train_lenet.sh在windows下的解决方案

    @tags: caffe python 在windows下配置caffe后,跑mnist手写数字识别的例子.发现train_lenet.sh不能运行. 那就写个python脚本替代吧. step1 定 ...

  4. 【BZOJ-3786】星系探索 Splay + DFS序

    3786: 星系探索 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 647  Solved: 212[Submit][Status][Discuss] ...

  5. 【BZOJ-1103】大都市meg 树状数组 + DFS序

    1103: [POI2007]大都市meg Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2009  Solved: 1056[Submit][Sta ...

  6. UOJ34 多项式乘法

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  7. Bzoj3004 吊灯

    Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 72  Solved: 46 Description        Alice家里有一盏很大的吊灯.所 ...

  8. 远程连接RabbitMQ失败

    远程连接RabbitMQ失败 为了避免污染宿主系统环境,于是在虚拟机中搭建了一个linux环境并且按照了rabbitmq-server.然后在远程连接的时候一直连接失败. 官网上面给的例子都是在本地使 ...

  9. .net图片验证码生成、点击刷新及验证输入是否正确

    ①创建ValidateCode.aspx,在ValidateCode.aspx.cs中加入如下代码.生成验证码图片,在页面上输出,输出jpeg格式. protected void Page_Load( ...

  10. 无法启动此程序,因为计算机中丢失MSVCP110.dll

    安装Visual C++ Redistributable for Visual Studio 2012 有arm.x86.x64有三个版本. 如果应用程序为debug版本而不是release版本,可能 ...