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. pyCharm最新2018激活码(转)

    原文地址:https://blog.csdn.net/u014044812/article/details/78727496 社区版和专业版区别: 因公司的需求,需要做一个爬取最近上映的电影.列车号. ...

  2. 常见报表的JS代码

    1.合并单元格 这个表格在报表里面算是比较典型的 1.里面的表格的列标题现在是写死的,其实这些可以通过配置进行 2.至于如果表头要进行合并(这种需求比较少,也比较容易实现) 3.至于统计:最好在后台按 ...

  3. Python开发之用户密码存储

    在各种线上应用中,用户名密码是用户身份认证的关键,它的重要性不言而喻.一方面,作为保护用户敏感数据的钥匙来说,一旦被破解,系统将敞开大门完全不设防.另一方面,密码这把钥匙本身就是非常敏感的数据:大多数 ...

  4. 新手之:SpringBoot ——Reids主从哨兵整合(CentOS7)

    一.Redis主从搭建(一台服务器模拟多个端口) 结构图:) 1.确保安装了Redis,我装在了/opt/redis目录下.可通过"whereis redis-cli"命令查看是否 ...

  5. CUDA 新版本 Visual Studio 和 CUDA 兼容性的小问题

    ▶ 升级到 Visual Studio 2017 和 CUDA 9.1 之后,直接编译以前的 CUDA C 程序出现了如下报错: 严重性 代码 说明 项目 文件 行 禁止显示状态 错误(活动) E00 ...

  6. Remove “Quick Access” entry in Eclipse Juno

    Here is a quick hack which doesn't require any plugin installation, instead you just need to add a f ...

  7. Maven(三)理解Maven核心概念

    转载自: http://www.cnblogs.com/holbrook/archive/2012/12/24/2830519.html 本文以类图的方式,介绍maven核心的12个概念以及相互之间的 ...

  8. ConcurrentDictionary内部机制粗解

    ConcurrentDictionary是线程安全类,是什么在保证? 内部类 private class Tables { internal readonly Node[] m_buckets; // ...

  9. Redis 与 Lua Script

    [Redis Script] 1.EVAL script numkeys key [key ...] arg [arg ...] 从 Redis 2.6.0 版本开始,通过内置的 Lua 解释器,可以 ...

  10. 和大于S的最小子数组 · Minimum Size Subarray Sum

    [抄题]: 给定一个由 n 个正整数组成的数组和一个正整数 s ,请找出该数组中满足其和 ≥ s 的最小长度子数组.如果无解,则返回 -1. 给定数组 [2,3,1,2,4,3] 和 s = 7, 子 ...