• .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的性能优势明显;

测试结果

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

最新文章

  1. 没有为扩展名“.html”注册的生成提供程序
  2. 使用ajax.dll时js脚本错误-XXX未定义
  3. xUtils 中的BitmapUtils 全面注释
  4. JavaScript 基础第九天(DOM第三天)
  5. 深入理解openstack网络架构(4)-----连接到public network
  6. 【poj1019】 Number Sequence
  7. java.lang.NoClassDefFoundError: antlr/ANTLRException
  8. hduoj 4706 Herding 2013 ACM/ICPC Asia Regional Online —— Warmup
  9. Android笔记——四大组件详解与总结
  10. Hibernate的一个注释 @Transient
  11. 【jQuery】
  12. ThinkPHP中处理验证码的问题
  13. cmd编译运行java
  14. c语言的一些易错知识积累
  15. git checkout --ours 【学习笔记】
  16. linux内核剖析(九)进程间通信之-信号signal
  17. Excel两列查找重复值
  18. 多人开发时Git下冲突的产生和解决
  19. python入门:1-100所有数的和
  20. mongodb,redis,mysql的区别和具体应用场景

热门文章

  1. React Native-安卓环境的搭建
  2. Redhat Linux 系统上安装JDK 1.7
  3. 带你剖析WebGis的世界奥秘----点和线的世界
  4. 从源码看Flask框架配置管理
  5. 《机器学习技法》---核型SVM
  6. AutoCAD二次开发(.Net)之创建图层Layer
  7. ubuntu下部署mongodb以及设置允许远程连接
  8. 设计模式(C#)——11代理模式
  9. BigDecimal 使用浅析
  10. Delphi - Indy 创建邮件自动发送服务