为什么获取和设置属性的PropertyInfo
方法如此之慢?如果我使用Reflection.Emit
构建委托,则速度要快得多。
他们是否正在做一些重要的事情,以便他们采取的时间是合理的?那是......我错过了一些东西,使用Reflection.Emit
来构建代理而不是使用PropertyInfo的GetValue
和SetValue
(除了开发速度)?
PS:请提供证据,不仅要猜测!
答案 0 :(得分:16)
RuntimePropertyInfo
(它是运行时类型的PropertyInfo
的具体子类)的实现通过反射调用getter和setter方法来实现GetValue
和SetValue
({ {1}}),而您生成的委托可能直接调用方法。因此,问题归结为:与编译调用相比,为什么MethodInfo.Invoke
这么慢?
当你反编译(或查看参考资料来源)RuntimeMethodInfo.Invoke
时,你可以看到这可能是因为RuntimeMethodInfo.Invoke
执行了很多任务:
运行时将代理编译为可执行本机代码时,将执行类似的一致性,安全性和可见性检查。它还会发送装箱/拆箱等的代码。但是,它只需要执行一次这些操作,然后可以保证代码可以安全执行。这使得实际方法调用非常便宜(加载参数并跳转到方法地址)。
相反,每次调用Invoke
(以及RuntimeMethodInfo.Invoke
/ GetValue
)都需要重复所有工作,因为上下文 - 参数,实例和返回的用法类型 - 不知道。这可能就是为什么它如此缓慢。
关于您可能缺少的内容:如果您发出自己的属性调用委托,您当然需要自己处理装箱/取消装箱,参考/退出参数等。
答案 1 :(得分: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)
}