c# - ConstructorInfo.Invoke 的 DynamicMethod,我需要考虑什么?

标签 c# invoke il dynamicmethod

我的问题是:

If I'm going to build a DynamicMethod object, corresponding to a ConstructorInfo.Invoke call, what types of IL do I need to implement in order to cope with all (or most) types of arguments, when I can guarantee that the right type and number of arguments is going to be passed in before I make the call?


背景

我正在对 IoC 容器进行第 3 次迭代,目前正在进行一些分析,以确定是否有任何区域可以轻松减少大量使用时间。

我注意到的一件事是,当解析为具体类型时,最终我会调用一个构造函数,使用 ConstructorInfo.Invoke ,传递我计算出的一组参数。

我注意到 invoke 方法有相当多的开销,我想知道其中大部分是否只是我所做的相同检查的不同实现。

例如,由于我有构造函数匹配代码,要为我传入的预定义参数名称、类型和值找到一个匹配的构造函数,这个特定的调用不可能不会以它结束应该能够处理正确数量的参数、正确的顺序、正确的类型和适当的值。

在执行包含对我的解析方法的一百万次调用的分析 session 时,然后将其替换为 DynamicMethod模仿 Invoke 调用的实现,分析时间是这样的:

  • ConstructorInfo.Invoke:1973 毫秒
  • 动态方法:93 毫秒

这约占此分析应用程序总运行时间的 20%。换句话说,通过用执行相同操作的 DynamicMethod 替换 ConstructorInfo.Invoke 调用,我能够在处理基本的工厂范围服务时减少 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

还有什么我需要考虑的吗?

请注意,我知道在“减少访问模式”下运行应用程序时创建动态方法可能不可用(有时大脑不会放弃这些术语),但在那种情况下我可以轻松检测到然后像以前一样调用原始构造函数,包括开销和所有。

最佳答案

对于值类型,步骤 l004 应该是 l004: unbox.any T

找出您需要生成的正​​确 IL 的最简单方法是使用一些测试代码查看 C# 编译器生成的内容。

static void Test(object[] args)
{
  TestTarget((string)args[0], (int)args[1], (DateTime?)args[2]);
}

static void TestTarget(string s, int i, DateTime? dt){}

编译为:

L_0000: ldarg.0 
L_0001: ldc.i4.0 
L_0002: ldelem.ref 
L_0003: castclass string
L_0008: ldarg.0 
L_0009: ldc.i4.1 
L_000a: ldelem.ref 
L_000b: unbox.any int32
L_0010: ldarg.0 
L_0011: ldc.i4.2 
L_0012: ldelem.ref 
L_0013: unbox.any [mscorlib]System.Nullable`1<valuetype [mscorlib]System.DateTime>
L_0018: call void Program::TestTarget(string, int32, valuetype [mscorlib]System.Nullable`1<valuetype [mscorlib]System.DateTime>)
L_001d: ret 

关于c# - ConstructorInfo.Invoke 的 DynamicMethod,我需要考虑什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1974877/

相关文章:

c# - Windows 服务结束后,Quartz.net 作业似乎仍然存在

javascript - ES6/TypeScript 中有 "operator overloading"吗? (或如何使对象可调用)

c# - ILGenerator 属性不是实例

c# - 在 C# 中更改 ComboBox 荧光笔的颜色

c# - 使用 LINQ 简化 foreach 循环(在每次迭代中选择两个对象)

c# - 使用 C# 发送具有特定字节数的 ping

c# - 将 Webbrowser 与 Control.invoke 结合使用

c# - 在另一个线程上捕获异常?

c# - 非赋值类的调用方法

c# - 查看从编译表达式生成的 IL 代码