Dapper.net的速度很快,最近看源码,原来他orm的实现是通过编写大量IL代码实现的。
使用DynamicMethod,自己编织一个给实体赋值的方法。这种写法效率很高,接近直接对属性赋值。比使用反射赋值效率高10倍左右。
下面分别使用Emit,反射,直接赋值100000次来进行对比测试。

public static Action<T, object> EmitSetter<T>(string propertyName)
{
var type = typeof(T);
var dynamicMethod = new DynamicMethod("EmitCallable", null, new[] { type, typeof(object) }, type.Module);
var iLGenerator = dynamicMethod.GetILGenerator(); var callMethod = type.GetMethod("set_" + propertyName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
var parameterInfo = callMethod.GetParameters()[];
var local = iLGenerator.DeclareLocal(parameterInfo.ParameterType, true); iLGenerator.Emit(OpCodes.Ldarg_1);
if (parameterInfo.ParameterType.IsValueType)
{
// 如果是值类型,拆箱
iLGenerator.Emit(OpCodes.Unbox_Any, parameterInfo.ParameterType);
}
else
{
// 如果是引用类型,转换
iLGenerator.Emit(OpCodes.Castclass, parameterInfo.ParameterType);
} iLGenerator.Emit(OpCodes.Stloc, local);
iLGenerator.Emit(OpCodes.Ldarg_0);
iLGenerator.Emit(OpCodes.Ldloc, local); iLGenerator.EmitCall(OpCodes.Callvirt, callMethod, null);
iLGenerator.Emit(OpCodes.Ret); return dynamicMethod.CreateDelegate(typeof(Action<T, object>)) as Action<T, object>;
}

下面是反射的写法

public static void ReflectSetter(object obj, string propertyName, object propertyValue)
{
var type = obj.GetType();
var propertyInfo = type.GetProperty(propertyName);
propertyInfo.SetValue(obj, propertyValue,null);
}

我们新建一个简单实体,添加一个属性。

public class Model
{
public string Name { get; set; }
}

下面进行测试

private void Button_Click(object sender, RoutedEventArgs e)
{
Model model = new Model();
TimeSpan ts1;
DateTime time1 = DateTime.Now; var emitSetter=EmitSetter<Model>("Name"); for (int i = ; i < ; i++)
{
emitSetter(model, "测试");
}
DateTime time2 = DateTime.Now; ts1 = time2 - time1;
Console.WriteLine("emit:"+ts1.TotalMilliseconds); DateTime t3 = DateTime.Now;
for (int i = ; i < ; i++)
{
ReflectSetter(model,"Name", "测试");
}
DateTime t4 = DateTime.Now;
ts1 = t4 - t3;
Console.WriteLine("reflect"+ts1.TotalMilliseconds); DateTime t5 = DateTime.Now;
for (int i = ; i < ; i++)
{
model.Name = "测试";
}
DateTime t6 = DateTime.Now;
ts1 = t6 - t5;
Console.WriteLine("直接赋值"+ts1.TotalMilliseconds);
}

运行结果如下图所示:

 
image.png

使用Emit执行时间大概是直接赋值的两倍,使用反射执行时间大概是直接赋值的三十多倍。Emit效率是反射的十倍以上。

使用Emit实现给实体赋值的更多相关文章

  1. asp.net DataReader DataTable 使用反射给给实体赋值

    asp.net 使用反射给给实体赋值 实体类继承此基类 using System.Reflection; using System.Data.SqlClient; using System.Data; ...

  2. c#使用emit方法DB,实体相互转换

    网上有很多ORM框架和数据库转换方法. c#由EF控制,但是大家知道的是影响效率和底层控制. 因此最近几个月一直在研究.最后产出了Hikari数据库连接池. 但是该库只是定位在连接池,无法有效进行后续 ...

  3. 【转】利用反射快速给Model实体赋值

    原文地址:http://blog.csdn.net/gxiangzi/article/details/8629064 试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有 ...

  4. EF架构~AutoMapper对象映射工具简化了实体赋值的过程

    回到目录 AutoMapper是一个.NET的对象映射工具,一般地,我们进行面向服务的开发时,都会涉及到DTO的概念,即数据传输对象,而为了减少系统的负载,一般我们不会把整个表的字段作为传输的数据,而 ...

  5. 利用反射快速给Model实体赋值

    试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...

  6. 利用反射快速给Model实体赋值 使用 Task 简化异步编程 Guid ToString 格式知多少?(GUID 格式) Parallel Programming-实现并行操作的流水线(生产者、消费者) c# 无损高质量压缩图片代码 8种主要排序算法的C#实现 (一) 8种主要排序算法的C#实现 (二)

    试想这样一个业务需求:有一张合同表,由于合同涉及内容比较多所以此表比较庞大,大概有120多个字段.现在合同每一次变更时都需要对合同原始信息进行归档一次,版本号依次递增.那么我们就要新建一张合同历史表, ...

  7. C# 同类型实体赋值

    #region 更新赋值,前者赋值给后者 public static void ShadowCopy(object a, object b) { if (a == null) return; if ( ...

  8. java两个实体公共属性赋值方法

    model1 info=new model1();info.setAge("123");info.setCode("1234");info.setName(&q ...

  9. MongoDB学习笔记~MongoDB实体中的值对象

    回到目录 注意,这里说的值对象是指在MongoDB实体类中的,并不是DDD中的值对象,不过,两者也是联系,就是它是对类的补充,自己本身没有存在的价值,而在值对象中,也是不需要有主键Id的,这与DDD也 ...

随机推荐

  1. liquibase使用

    1. 创建表 drop database if exists mybatis; create database mybatis; use mybatis; create table mybatis.C ...

  2. Spring Boot实践——事件监听

    借鉴:https://blog.csdn.net/Harry_ZH_Wang/article/details/79691994 https://blog.csdn.net/ignorewho/arti ...

  3. 人脸检测及识别python实现系列(2)——识别出人脸

    人脸检测及识别python实现系列(2)——识别出人脸 http://www.cnblogs.com/neo-T/p/6430583.html

  4. 使用cnpm代替npm

    淘宝 NPM 镜像 这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步. 当前 registry.npm.taobao.or ...

  5. Socket调用方式(同步,异步,阻塞,非阻塞)

    同步: 我调用一个功能,该功能没有结束前,我死等结果. 异步: 当一个异步过程调用发出后,调用者不能立刻得到结果.该功能在完成后,通过状态.通知和回调来通知调用者. 同步和非同步关注的是调用者是否等待 ...

  6. 38.Count and Say 报数

    [抄题]: The count-and-say sequence is the sequence of integers beginning as follows:1, 11, 21, 1211, 1 ...

  7. py学习之FTP

    1.FTP之参数解析与命令分发 a) 层级目录如下 b) 配置文件如下 #!/usr/bin/env python # -*- coding:utf8 -*- import socket sk=soc ...

  8. re 正则模块

    re模块(* * * * *) 就其本质而言,正则表达式(或 RE)是一种小型的.高度专业化的编程语言,(在Python中)它内嵌在Python中,并通过 re 模块实现.正则表达式模式被编译成一系列 ...

  9. oepnni安装

    sudo apt-get install libopenni-dev libopenni2-dev / apt-get install libqhull-dev

  10. [Selenium]How to click on a hidden link ,move to the drop down menu and click submenu

    <table id="_paid_19" class="GOMainTable" cellspacing="0" cellpaddin ...