使用Reflection.Emit匹配现有构造函数

时间:2010-03-30 16:24:52

标签: .net cil reflection.emit

首先,这是C#代码和反汇编的IL:

public class Program<T>
{
    private List<T> _items;

    public Program(T x, [Microsoft.Scripting.ParamDictionary] Microsoft.Scripting.IAttributesCollection col)
    {
        _items = new List<T>();
        _items.Add(x);
    }
}

这是构造函数的IL:

.method public hidebysig specialname rtspecialname 
        instance void  .ctor(!T x,
                             class [Microsoft.Scripting]Microsoft.Scripting.IAttributesCollection col) cil managed
{
  .param [2]
  .custom instance void [Microsoft.Scripting]Microsoft.Scripting.ParamDictionaryAttribute::.ctor() = ( 01 00 00 00 ) 
  // Code size       34 (0x22)
  .maxstack  8
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  nop
  IL_0007:  nop
  IL_0008:  ldarg.0
  IL_0009:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<!T>::.ctor()
  IL_000e:  stfld      class [mscorlib]System.Collections.Generic.List`1<!0> class Foo.Program`1<!T>::_items
  IL_0013:  ldarg.0
  IL_0014:  ldfld      class [mscorlib]System.Collections.Generic.List`1<!0> class Foo.Program`1<!T>::_items
  IL_0019:  ldarg.1
  IL_001a:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<!T>::Add(!0)
  IL_001f:  nop
  IL_0020:  nop
  IL_0021:  ret
} // end of method Program`1::.ctor

我试图通过自己发布来了解IL代码。这就是我设法发出的:

.method public hidebysig specialname rtspecialname 
        instance void  .ctor(!T A_1,
                             class [Microsoft.Scripting]Microsoft.Scripting.IAttributesCollection A_2) cil managed
{
  // Code size       34 (0x22)
  .maxstack  4
  IL_0000:  ldarg.0
  IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
  IL_0006:  ldarg.0
  IL_0007:  newobj     instance void class [mscorlib]System.Collections.Generic.List`1<!T>::.ctor()
  IL_000c:  stfld      class [mscorlib]System.Collections.Generic.List`1<!0> class MyType<!T>::_items
  IL_0011:  ldarg.0
  IL_0012:  ldfld      class [mscorlib]System.Collections.Generic.List`1<!0> class MyType<!T>::_items
  IL_0017:  ldarg.s    A_1
  IL_0019:  nop
  IL_001a:  nop
  IL_001b:  nop
  IL_001c:  callvirt   instance void class [mscorlib]System.Collections.Generic.List`1<!T>::Add(!0)
  IL_0021:  ret
} // end of method MyType::.ctor

我无法弄清楚有一些差异。我真的很亲密......

  1. 如何处理参数属性(ParamDictionaryAttribute)?我找不到“自定义”操作码。

  2. .param [2]重要吗?我该怎么发出它?

  3. 为什么C#代码堆栈大小为8,而我的发布版本为4?这很重要吗?

2 个答案:

答案 0 :(得分:3)

.custom不是操作码,它是应用自定义属性的方式。这是宣言的一部分。它与.param紧密绑定。 .param[2]告诉我们现在我们将讨论第二个参数。 .custom应用指定的参数。请查看MSIL spec,第225页和201和199(对于.maxstack)

要在ctor上的参数调用DefineParameter上设置自定义属性,您就可以ParameterBuilder调用SetCustomAttribute()

答案 1 :(得分:1)

- &GT; 1./2。在构造函数构建器上使用DefineParameter()(而不是使用type[]定义它们),然后您可以执行SetCustomAttribute()将属性应用于参数。

- &GT;我觉得这并不重要。它基本上指定了方法能够运行多少堆栈。