如何使用 TypeBuilder 创建具有基类型静态字段的派生类型?

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

我在使用 TypeBuilder 动态创建派生类型时遇到问题,该派生类型具有基类型的静态字段,并初始化为所创建类型的新实例。

本质上,我想动态创建它:

public abstract class Base {
    ...
}

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

使用 SharpLab,我看到派生的 class 的以下 IL:

.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

我的 TypeBuilder 有以下内容,试图重新创建显示的 IL:

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;
}

但是当我使用它时,我得到一个 InvalidProgramException

多亏了 Kirk Woll 的提示,我才能够发现我的错误。

OpCodes.Stsfld 不是 OpCodes.Stfld

(捂脸)