反射,Expression Tree,IL Emit 属性操作对比
.net的反射(Reflection) 是.Net中获取运行时类型信息的一种方法,通过反射编码的方式可以获得 程序集,模块,类型,元数据等信息。
反射的优点在于微软提供的API调用简单,使用方便;表达式树(Expression Tree)表达式树以树形数据结构表示代码,其中每一个节点都是一种表达式,表达式树经过编译后生成的直接是IL代码;
IL Emit 是直接操作IL的执行过程,对IL代码精细化控制;
属性赋值操作 PropertyInfo.GetValue/SetValue是反射中常用的功能;
三种实现方式的性能对比:
public class Bar
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Foo
{
public Bar Bar { get; set; }
public static void SetReflection(Foo foo, Bar bar)
{
var property = foo.GetType().GetProperty("Bar");
property.SetValue(foo, bar);
}
public static Action<Foo, Bar> SetExpression()
{
var property = typeof(Foo).GetProperty("Bar");
var target = Expression.Parameter(typeof(Foo));
ParameterExpression propertyValue = Expression.Parameter(typeof(Bar));
//var setPropertyValue = Expression.Call(target, property.GetSetMethod(), propertyValue);
BinaryExpression setPropertyValue = Expression.Assign(Expression.Property(target, property), propertyValue);
var setAction = Expression.Lambda<Action<Foo, Bar>>(setPropertyValue, target, propertyValue).Compile();
return setAction;
}
public static Action<Foo, Bar> SetEmit()
{
var property = typeof(Foo).GetProperty("Bar");
DynamicMethod method = new DynamicMethod("SetValue", null, new Type[] { typeof(Foo), typeof(Bar) });
ILGenerator ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.Emit(OpCodes.Ldarg_1);
ilGenerator.EmitCall(OpCodes.Callvirt, property.GetSetMethod(), null);
ilGenerator.Emit(OpCodes.Ret);
method.DefineParameter(1, ParameterAttributes.In, "obj");
method.DefineParameter(2, ParameterAttributes.In, "value");
var setAction2 = (Action<Foo, Bar>)method.CreateDelegate(typeof(Action<Foo, Bar>));
return setAction2;
}
public static void Test()
{
var act1 = Foo.SetExpression();
var act2 = Foo.SetEmit();
var st = new Stopwatch();
st.Start();
for (int i = 0; i < 1000000; i++)
{
var foo = new Foo { };
var bar = new Bar { Id = 1, Name = "name" };
Foo.SetReflection(foo, bar);
}
Console.WriteLine("Reflection " + st.ElapsedMilliseconds);
st.Restart();
for (int i = 0; i < 1000000; i++)
{
var foo = new Foo { };
var bar = new Bar { Id = 1, Name = "name" };
act1(foo, bar);
}
Console.WriteLine("Expression " + st.ElapsedMilliseconds);
st.Restart();
for (int i = 0; i < 1000000; i++)
{
var foo = new Foo { };
var bar = new Bar { Id = 1, Name = "name" };
act2(foo, bar);
}
Console.WriteLine("Emit " + st.ElapsedMilliseconds);
}
}
循环多次操作性能对比还是明显的表达式数和emit的性能优势明显;
测试结果

但是只循环一次的话 三种实现方式性能是无差别的,所以在一般情况下,反射的性能损失是可以忽略的;

反射,Expression Tree,IL Emit 属性操作对比的更多相关文章
- 【java】【反射】反射实现判断发生了修改操作,判断两个对象是否发生属性值的变更,判断两个List集合内对象的属性值是否发生变更
java的反射实现: 判断发生了修改操作,判断两个对象是否发生属性值的变更,判断两个List集合内对象的属性值是否发生变更 今日份代码: package com.sxd.streamTest; imp ...
- C# 反射之属性操作
一.反射-类操作 //1.获取对象所有的属性名 Student stu = new Student(); //获取当前类名称 Console.WriteLine(stu.GetType().Name) ...
- 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习
反射实现Model修改前后的内容对比 在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...
- C#反射发出System.Reflection.Emit学习
一.System.Reflection.Emit概述 Emit,可以称为发出或者产生.与Emit相关的类基本都存在于System.Reflection.Emit命名空间下.反射,我们可以取得形如程序集 ...
- Expression Tree 扩展MVC中的 HtmlHelper 和 UrlHelper
表达式树是LINQ To everything 的基础,同时各种类库的Fluent API也 大量使用了Expression Tree.还记得我在不懂expression tree时,各种眼花缭乱的A ...
- 使用Expression Tree构建动态LINQ查询
这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法.这个在很多系统开发过程中是非常有用的. 我这里给 ...
- Reflection和Expression Tree解析泛型集合快速定制特殊格式的Json
很多项目都会用到Json,而且大部分的Json都是格式固定,功能强大,转换简单等,标准的key,value集合字符串:直接JsonConvert.SerializeObject(List<T&g ...
- 转载Expression Tree揭秘
概述 在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHiber ...
- [转]打造自己的LINQ Provider(上):Expression Tree揭秘
概述 在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHiber ...
随机推荐
- JavaScript循环出现的问题——用闭包来解决
在for循环中,数组长度为3,我本来是想对每个循环的元素绑定一个点击事件的,结果点击后控制台输出全部为1. for (var i = 0; i < data.data.length; i++) ...
- 从零开始学习springboot之热部署的配置
各位看官大家好,博主之前因为毕业设计以及毕业旅游耽搁了好长一段时间没有更新博客了,从今天起又会慢慢开始学习啦. 今天主要是来学习springboot热部署的配置. 一. 热部署 我们通常在修改某些文件 ...
- 源码解读 Spring Boot Profiles
前言 上文<一文掌握 Spring Boot Profiles> 是对 Spring Boot Profiles 的介绍和使用,因此本文将从源码角度探究 Spring Boot Profi ...
- 常用maven 命令
重新依赖:mvn package -U -DskipTest=true; 在本地安装jar包:mvn install 清除产生的项目:mvn clean 运行测试:mvn test 上传到私服:mvn ...
- c# 将dwg文件转化为pdf
https://blog.csdn.net/mywaster/article/details/50220379 最近做一个项目,要求将dwg文件转化为pdf,开发工具VS2010 + AutoCad ...
- Spring boot实战项目整合阿里云RocketMQ (非开源版)消息队列实现发送普通消息,延时消息 --附代码
一.为什么选择RocketMQ消息队列? 首先RocketMQ是阿里巴巴自研出来的,也已开源.其性能和稳定性从双11就能看出来,借用阿里的一句官方介绍:历年双 11 购物狂欢节零点千万级 TPS.万亿 ...
- 二.安全NA之ASA基础
一.ASA常用命令 show run interface #查看接口配置 show ip address #查看IP地址 show conn #查看防火墙状态信息,U代表up:I,代表进流量:O,代表 ...
- python3.6.6在CentOS7上的安装
Python官网:https://www.python.org/ 下载指定版本的软件包: [root@General data]# yum clean all && yum rep ...
- .NET Core 很酷,你不得不知!
转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者.原文出处:https://www.infoq.cn/article/xPTBAR9-oJcVtUjTQ0tK ...
- docker安装Ubuntu以及ssh连接
一.简述 环境: Windows10 docker:2.1.0.1 二.开始安装 Windows的docker安装就不再多说了,网上有很多教程 在docker的hub仓库中,有专门的ubuntu系统. ...