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效率是反射的十倍以上。

最新文章

  1. IOS----友盟推送详解
  2. 001. 为input type=text 时设置默认值
  3. NS_ENUM和NS_OPTIONS区别
  4. Android设置背景图像重复【整理自网络】
  5. quartus ii 中文注释乱码解决办法
  6. PCL—低层次视觉—点云滤波(初步处理)
  7. js限制文本框只能输入数字
  8. 学习java随笔第三篇:java的基本数据类型
  9. Android Studio代码着色插件
  10. 模板应用--UI线程与worker线程同步 模仿c# invoke
  11. maven GroupID和ArtifactID填什么
  12. 01_Python入门
  13. Ubuntu硬盘空间清理
  14. LeetCode算法题-Subdomain Visit Count(Java实现)
  15. python 中的__new__方法
  16. 机器学习用Pandas实现数据库的读取
  17. Django框架详细介绍---认证系统
  18. (3)Linux的哲学思想
  19. SQL触发器 常用语句
  20. DataFrame按行读取:DataFrame之values

热门文章

  1. WPF DatePicker 默认显示当前时间
  2. sublime text3最新版本注册码(build 3143)
  3. JAVA获取txt文件内容
  4. sql中纵表变横表
  5. Linux中shell变量$0,$?等含义
  6. Mysql,重复字段只取其中一行
  7. qemu模拟器下编译运行基于riscv指令集的Linux操作系统
  8. 265. Paint House II 房子涂色K种选择的版本
  9. 解题报告-603. Consecutive Available Seats
  10. 使用delphi 开发多层应用(二十一)使用XE5 RESTClient 直接访问kbmmw 数据库