如何使用 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
。
(捂脸)
我在使用 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
。
(捂脸)