'How do I use TypeBuilder to create derived type with static field of base type?

I am having an issue using TypeBuilder to dynamically create a derived type that has a static field of the base type, that is initialized to a new instance of the created type.

Essentially, I want to create this dynamically:

public abstract class Base {
    ...
}

public class Imp : Base
{
  public static readonly Base B;
  
  static Imp(){
    B = new Imp();
  }
  ...
}

Using SharpLab, I see the following IL for the derived class:

.class public auto ansi Imp
    extends Base
{
    // Fields
    .field public static initonly class Base B

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

        IL_0000: nop
        IL_0001: newobj instance void Imp::.ctor()
        IL_0006: stsfld class Base Imp::B
        IL_000b: ret
    } // end of method Imp::.cctor

    .method public hidebysig specialname rtspecialname 
        instance void .ctor () cil managed 
    {
        // Method begins at RVA 0x2066
        // Code size 8 (0x8)
        .maxstack 8

        IL_0000: ldarg.0
        IL_0001: call instance void Base::.ctor()
        IL_0006: nop
        IL_0007: ret
    } // end of method Imp::.ctor

} // end of class Imp

I have the following for my TypeBuilder, in an attempt to recreate the IL shown:

private static Type CreateImp()
{
    var assyBldr = AssemblyBuilder.DefineDynamicAssembly(
        new AssemblyName("TestAssy"), AssemblyBuilderAccess.RunAndCollect);
    var moduleBldr = assyBldr.DefineDynamicModule("TestMod");
    var typeBldr = moduleBldr.DefineType("Imp",
        TypeAttributes.Public |
        TypeAttributes.Sealed |
        TypeAttributes.Class |
        TypeAttributes.AnsiClass |
        TypeAttributes.AutoLayout |
        TypeAttributes.BeforeFieldInit |
        TypeAttributes.AutoClass,
        typeof(Base));

    // Add the static instance field
    var fieldBldr = typeBldr.DefineField("B", 
        typeof(Base), 
        FieldAttributes.Public | 
        FieldAttributes.Static | 
        FieldAttributes.InitOnly);

    var ctorBldr = typeBldr.DefineConstructor(
        MethodAttributes.Private |
        MethodAttributes.Static,
        CallingConventions.Standard,
        Type.EmptyTypes);

    var ctorILGen = ctorBldr.GetILGenerator();

    var objCtor = typeBldr.DefineDefaultConstructor(MethodAttributes.Public);
            
    ctorILGen.Emit(OpCodes.Newobj, objCtor);
    ctorILGen.Emit(OpCodes.Stfld, fieldBldr);
    ctorILGen.Emit(OpCodes.Ret);
            
    var type = typeBldr.CreateType();

    return type;
}

but when I use it, I get an InvalidProgramException



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source