• .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 属性操作对比的更多相关文章

  1. 【java】【反射】反射实现判断发生了修改操作,判断两个对象是否发生属性值的变更,判断两个List集合内对象的属性值是否发生变更

    java的反射实现: 判断发生了修改操作,判断两个对象是否发生属性值的变更,判断两个List集合内对象的属性值是否发生变更 今日份代码: package com.sxd.streamTest; imp ...

  2. C# 反射之属性操作

    一.反射-类操作 //1.获取对象所有的属性名 Student stu = new Student(); //获取当前类名称 Console.WriteLine(stu.GetType().Name) ...

  3. 反射实现Model修改前后的内容对比 【API调用】腾讯云短信 Windows操作系统下Redis服务安装图文详解 Redis入门学习

    反射实现Model修改前后的内容对比   在开发过程中,我们会遇到这样一个问题,编辑了一个对象之后,我们想要把这个对象修改了哪些内容保存下来,以便将来查看和追责. 首先我们要创建一个User类 1 p ...

  4. C#反射发出System.Reflection.Emit学习

    一.System.Reflection.Emit概述 Emit,可以称为发出或者产生.与Emit相关的类基本都存在于System.Reflection.Emit命名空间下.反射,我们可以取得形如程序集 ...

  5. Expression Tree 扩展MVC中的 HtmlHelper 和 UrlHelper

    表达式树是LINQ To everything 的基础,同时各种类库的Fluent API也 大量使用了Expression Tree.还记得我在不懂expression tree时,各种眼花缭乱的A ...

  6. 使用Expression Tree构建动态LINQ查询

    这篇文章介绍一个有意思的话题,也是经常被人问到的:如何构建动态LINQ查询?所谓动态,主要的意思在于查询的条件可以随机组合,动态添加,而不是固定的写法.这个在很多系统开发过程中是非常有用的. 我这里给 ...

  7. Reflection和Expression Tree解析泛型集合快速定制特殊格式的Json

    很多项目都会用到Json,而且大部分的Json都是格式固定,功能强大,转换简单等,标准的key,value集合字符串:直接JsonConvert.SerializeObject(List<T&g ...

  8. 转载Expression Tree揭秘

    概述 在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHiber ...

  9. [转]打造自己的LINQ Provider(上):Expression Tree揭秘

    概述 在.NET Framework 3.5中提供了LINQ 支持后,LINQ就以其强大而优雅的编程方式赢得了开发人员的喜爱,而各种LINQ Provider更是满天飞,如LINQ to NHiber ...

随机推荐

  1. HTML/CSS:div居中和div内部元素垂直居中(1)

    div居中 div水平和垂直居中,text-align和vertical-align不起作用,因为标签div没有这两个属性,所以再css中设置这两个值不能居中的效果 1. div水平居中:设置marg ...

  2. Redis——发布和订阅

    发布与订阅(又称pub/sub),订阅者(listener)负责订阅频道(channel),发送者(publisher)负责向频道发送二进制字符串消息(binary string message).每 ...

  3. Vue中拆分视图层代码的5点建议

    目录 一.框架的定位 二. Vue开发中的script拆分优化 1.组件划分 2.剥离业务逻辑代码 3. 剥离数据转换代码 4. 善用computed和filters处理数据展示 5. 使用direc ...

  4. 洛谷 P1120 小木棍

    题意简述 给出n个数,求最小的l,使n个数可分成若干组,每组和都为l. 题解思路 暴力搜索+剪枝 代码 #include <cstdio> #include <cstdlib> ...

  5. Linux expect 介绍和用法

    expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信. expect自动交互流程: spawn启动指定进程---expect获取指定关键字--- ...

  6. 小白学Python(4)——用Python创建PPT

    python-pptx是一个用于创建和更新PowerPoint(.pptx)文件的Python库. 典型的用途是从数据库内容生成自定义的PowerPoint演示文稿,可通过单击Web应用程序中的链接进 ...

  7. 基于开源中文分词工具pkuseg-python,我用张小龙的3万字演讲做了测试

    做过搜索的同学都知道,分词的好坏直接决定了搜索的质量,在英文中分词比中文要简单,因为英文是一个个单词通过空格来划分每个词的,而中文都一个个句子,单独一个汉字没有任何意义,必须联系前后文字才能正确表达它 ...

  8. vscode保存代码,自动按照eslint规范格式化代码设置

    # vscode保存代码,自动按照eslint规范格式化代码设置 编辑器代码风格一致,是前端代码规范的一部分.同一个项目,或者同一个小组,保持代码风格一致很必要.就拿vue项目来说,之前做的几个项目, ...

  9. 《深入理解Java虚拟机》- JVM是如何实现反射的

    Java反射学问很深,这里就浅谈吧.如果涉及到方法内联,逃逸分析的话,我们就说说是什么就好了.有兴趣的可以去另外看看,我后面可能也会写一下.(因为我也不会呀~) 一.Java反射是什么? 反射的核心是 ...

  10. copy好文“IT34岁危机破解心法”

    在博客园中偶然发现一个好文,收藏并记录以下.在工作中更多的从企业单位用人角度去思考,或许能在职场及职业规划中更加的游刃有余,有的放矢.下面是原文. 本文题目虽是“IT人34岁危机”破解心法,但内容同样 ...