我的问题是这样的:
如果我要构建一个DynamicMethod对象,对应一个ConstructorInfo.Invoke调用,当我可以保证正确的类型时,我需要实现什么类型的 IL 以处理所有(或大多数)类型的参数在我拨打电话之前要传入多少个参数?
背景
我正在进行 IoC 容器的第三次迭代,目前正在做一些分析,以确定是否有任何区域可以轻松节省大量使用时间。
我注意到的一件事是,当解析为具体类型时,最终我会使用ConstructorInfo.Invoke调用构造函数,并传入我已经计算出的参数数组。
我注意到调用方法有相当多的开销,我想知道其中大部分是否只是我所做的相同检查的不同实现。
例如,由于我拥有的构造函数匹配代码,要为我传入的预定义参数名称、类型和值找到匹配的构造函数,这个特定的调用调用不可能最终得到它应该能够的东西以正确的顺序、正确的类型和适当的值来处理,例如正确数量的参数。
在执行包含对我的 resolve 方法的一百万次调用的分析会话,然后将其替换为模仿 Invoke 调用的DynamicMethod实现时,分析时间是这样的:
- ConstructorInfo.Invoke:1973 毫秒
- 动态方法:93ms
这约占此分析应用程序总运行时间的 20%。换句话说,通过将 ConstructorInfo.Invoke 调用替换为具有相同功能的 DynamicMethod,我能够在处理基本的工厂范围服务时减少 20% 的运行时间(即,所有解析调用都以构造函数调用结束)。
我认为这是相当重要的,并且值得仔细研究在这种情况下为构造函数构建一个稳定的 DynamicMethod 生成器需要做多少工作。
因此,动态方法将接受一个对象数组,并返回构造的对象,我已经知道有问题的 ConstructorInfo 对象。
因此,看起来动态方法将由以下 IL 组成:
l001: ldarg.0 ; the object array containing the arguments
l002: ldc.i4.0 ; the index of the first argument
l003: ldelem.ref ; get the value of the first argument
l004: castclass T ; cast to the right type of argument (only if not "Object")
(repeat l001-l004 for all parameters, l004 only for non-Object types,
varying l002 constant from 0 and up for each index)
l005: newobj ci ; call the constructor
l006: ret
还有什么我需要考虑的吗?
请注意,我知道在“减少访问模式”下运行应用程序时创建动态方法可能不可用(有时大脑不会放弃这些术语),但在这种情况下,我可以很容易地检测到这一点并且只是像以前一样调用原始构造函数,开销和所有。