Using Reflection.Emit to match an existing constructor

First, here is the C # code and the parsed 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); } } 

Here is the IL of this constructor:

 .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 

I am trying to understand the IL code by emitting it myself. This is what I managed to emit:

 .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 

There are a few differences that I simply cannot understand. I am very close ...

  • How can I take care of a parameter attribute (ParamDictionaryAttribute)? I can not find the "user" operation code.

  • Is .param [2] important? How can I emit this?

  • Why is the C # code stack size equal to 8 and my released version is 4? It is important?

+4
source share
2 answers

.custom not an operation code; it is a way of applying a special attribute. This is part of the declaration. It is closely related to .param . .param[2] says that now we will talk about the 2nd parameter. .custom applies the specified parameter. Take a look at the MSIL specification , pages 225 and 201 and 199 (for .maxstack)

To set a custom attribute when calling the DefineParameter parameter on ctor, and you get a ParameterBuilder call to SetCustomAttribute() on it

+3
source

-> 1./2. Use DefineParameter() in the constructor constructor (instead of defining with type[] ), and then you can do SetCustomAttribute() to apply the attribute to the parameter.

-> 3. It doesn’t matter, I think. It basically determines how much stack should be available in order for the method to work.

+1
source

Source: https://habr.com/ru/post/1305570/


All Articles