为什么PropertyInfo SetValue和GetValue这么慢?

Mig*_*elo 16 .net reflection reflection.emit propertyinfo

为什么PropertyInfo获取和设置属性的方法如此之慢?如果我使用构建委托Reflection.Emit,它会快得多.

他们是否正在做一些重要的事情,以便他们采取的时间是合理的?这是...我失去的东西通过Reflection.Emit建立代表,而不是usign的GetValueSetValue的的PropertyInfo(预留的发展速度)?

PS:请证明,不仅要猜测!

Fab*_*ied 16

的实施RuntimePropertyInfo(这是具体子类PropertyInfo的运行时类型)实现GetValue,并SetValue通过通过反射调用getter和setter方法(MethodInfo.Invoke),而你产生委托可能直接调用方法.因此,问题归结为:RuntimeMethodInfo.Invoke与编译调用相比,为什么这么慢?

当您反编译(或查看参考源)时RuntimeMethodInfo.Invoke,您可以看到这可能是因为Invoke执行了很多任务:

  • 它执行一致性检查(传递的参数的数量和类型是否与签名匹配?传递的实例是否与声明类型匹配?虽然方法是静态的,但是传递了一个实例?),
  • 它执行可见性和(如果绕过可见性检查)安全检查,
  • 它解包参数数组,以特殊方式处理ref参数,以便以后可以将它们写回
  • 如有必要,它会取消装箱参数,
  • 它需要根据与RuntimeMethodHandle关联的运行时类型句柄和方法句柄找到方法指针,然后调用该方法,
  • 如有必要,它会包含返回值
  • 它将所有参考/输出参数放入参数数组中.

运行时将代理编译为可执行本机代码时,将执行类似的一致性,安全性和可见性检查.它还会发送装箱/拆箱等的代码.但是,它只需要执行一次这些操作,然后可以保证代码可以安全执行.这使得实际方法调用非常便宜的操作(加载参数并跳转到方法地址).

相反,每次调用RuntimeMethodInfo.Invoke(因此对GetValue/ SetValue)都需要重复所有工作,因为上下文 - 参数,实例和返回类型的用法 - 是未知的.这可能就是为什么它如此缓慢.

关于你可能缺少的东西:如果你发出自己的属性调用委托,你当然需要自己处理装箱/拆箱,ref/out参数等.


Fri*_*ied 13

没有必要使用Emit.使用Expression要容易得多.您可以按照SO中的说明加快访问速度 .辅助类为getter或setter创建一个"方法指针"(Action/Func).如果重复使用Action/Func,您将能够像普通的setter一样快速地执行.

   // creating setter (once)
   var propertyInfo = typeof(T).GetProperty(field);
   var setter = FastInvoke.BuildUntypedSetter<T>(propertyInfo));

   // usage somehow later in a loop of data
   foreach(var myobject in MySource)
   {
     setter(myobject, myValue)
   }
Run Code Online (Sandbox Code Playgroud)