mercredi 3 avril 2019

How to remove .local init from constructor created with Reflection.Emit?

I want to build a class with Relfection.Emit to dynamically create Proxy classes at runtime. Because I use Linq Select with Lambda Expressions in my class, the generated IL code contains a nested class to store the closures.

When i build the class in C# and look at the generated IL code from the compiler, it looks like that:

...
.class nested private auto ansi sealed serializable beforefieldinit '<>c'
        extends [mscorlib]System.Object
    {
        .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
            01 00 00 00
        )
        // Fields
        .field public static initonly class Namespace.ThemaVOMultiValueProxy/'<>c' '<>9'


        // Methods
        .method private hidebysig specialname rtspecialname static 
            void .cctor () cil managed 
        {
            // Method begins at RVA 0x78808
            // Code size 11 (0xb)
            .maxstack 8

            IL_0000: newobj instance void Namespace.ThemaVOMultiValueProxy/'<>c'::.ctor()
            IL_0005: stsfld class Namespace.ThemaVOMultiValueProxy/'<>c' Namespace.ThemaVOMultiValueProxy/'<>c'::'<>9'
            IL_000a: ret
        } // end of method '<>c'::.cctor

        ...

    } // end of class <>c
...

So that´s what I want to create myself with Reflection.Emit.

My C# code for that looks like that:

...
var c = typeBuilder.DefineNestedType("closures", TypeAttributes.NestedPrivate | TypeAttributes.AutoClass | TypeAttributes.AnsiClass | TypeAttributes.Sealed | TypeAttributes.Serializable | TypeAttributes.BeforeFieldInit);
var closureField_proxy_9 = c.DefineField("proxy_9", c, FieldAttributes.Public | FieldAttributes.Static | FieldAttributes.InitOnly);

var closureStaticConstructor = c.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Any, Type.EmptyTypes);
closureStaticConstructor.InitLocals = false; // seems to have no effect
var closureStaticConstructorILGenerator = closureStaticConstructor.GetILGenerator();
closureStaticConstructorILGenerator.Emit(Ldarg_0);
closureStaticConstructorILGenerator.Emit(Call, objectConstructor);
closureStaticConstructorILGenerator.Emit(Nop);
closureStaticConstructorILGenerator.Emit(Ret);
...

And that generates that IL:

...
// Nested Types
.class nested private auto auto sealed serializable beforefieldinit closures
    extends [mscorlib]System.Object
{
    // Fields
    .field public static initonly class RZL.KIS.WPF.ViewObject.ThemaVO_MultiValueProxy/closures proxy_9

    // Methods
    .method public hidebysig specialname rtspecialname 
        instance vararg void .ctor () cil managed 
    {
        // Method begins at RVA 0x2050
        // Code size 8 (0x8)
        .maxstack 2
        .locals /* Signature type sequence must have at least one element. */ (
        )

        IL_0000: ldarg.0
        IL_0001: call instance void [mscorlib]System.Object::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method closures::.ctor

} // end of class closures
...

My question now is: How to I remove that .locals /* Signature type sequence must have at least one element. */ block in the created constructor? I don´t need it, because I don´t have any local variables or parameters here.

Thank you!





Aucun commentaire:

Enregistrer un commentaire