2009-12-29 120 views
3

我的问题是这样的:ConstructorInfo.Invoke的DynamicMethod,我需要考虑什么?

如果我要建立一个DynamicMethod对象,对应于ConstructorInfo.Invoke电话,做什么类型的IL我需要,以实现应对所有(或大部分)类型当我能保证在我打电话之前要传递正确的类型和数量的参数?


背景

我对我的我的IoC容器的第3次迭代,目前做了一些分析,以找出是否有任何方面,我可以很容易刮掉大量的时间正在使用。

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

我注意到的是,invoke方法有很多开销,我想知道这是否只是我做的同样的检查的不同实现。例如,由于我有构造函数匹配代码,为了找到一个匹配的构造函数,用于我传入的预定义的参数名称,类型和值,这个特定的调用调用不会以某种方式结束它应该能够以正确的顺序,正确的类型和适当的值处理正确数量的参数。

在做包含万个电话给我解决方法的分析会话,然后用DynamicMethod实现模仿调用调用替换它,仿形时序是这样的:

  • ConstructorInfo.Invoke:1973ms
  • DynamicMethod的:93ms

这占了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 

还有什么我需要考虑?

注意,我知道,创建动态方法运行在“减少访问模式”的应用程序(有时大脑就不会放弃这些条款)时,可能会无法使用,但在这种情况下,我可以很容易地检测并且像以前一样调用原始的构造函数,开销和所有。

回答

1

对于值类型步骤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 
+0

所以基本上,因为我的Type对象的每个参数,如果Type.IsValueType返回,而不是castclass TYPE真的,我用unbox.any TYPE呢? – 2009-12-29 19:01:17

+0

是的,这应该足以涵盖所有参数类型。 – 2009-12-29 21:17:14

+0

谢谢,我会添加一堆单元测试来验证我能想到的所有组合,但是这看起来可能只是工作:) – 2009-12-29 21:54:53

0

有可更容易,速度更快与反思工作库。例如,Fasterflect可以生成用于调用任何构造函数的IL - 您只需将它传递给您想要在构造函数上使用的参数即可。

// note: class must have constructor with (int,string,string) signature 
object obj = someType.CreateInstance(new { id=1, name="jens", foo="bar" }); 

该库还能够探测一个合适的构造函数调用,如果你没有一组构造函数完全匹配的参数。

// try to map id, name and foo to constructor parameters 
// allows changing the order and permit fallback to setting fields/properties 
// e.g. might result in call to ctor(string,string) and set field "id" 
object obj = someType.TryCreateInstance(new { id=1, name="jens", foo="bar" }); 

声明:我作为贡献者参与了上述项目。

相关问题