C# 如何使用Reflection.Emit创建静态字段

C# 如何使用Reflection.Emit创建静态字段,c#,.net,reflection,emit,C#,.net,Reflection,Emit,我正在尝试使用Reflection.Emit创建静态场 但是,当我尝试加载它时,会得到一个InvalidProgrammeException 下面的代码再现了我的问题 该行: generator.Emit(OpCodes.Ldsfld, builderField); 导致以下异常: Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program.

我正在尝试使用Reflection.Emit创建静态场

但是,当我尝试加载它时,会得到一个InvalidProgrammeException

下面的代码再现了我的问题

该行:

generator.Emit(OpCodes.Ldsfld, builderField);
导致以下异常:

Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program.
没有这一行,程序运行正常,并按预期返回“Test”

        var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
            new AssemblyName(Guid.NewGuid().ToString()),
            AssemblyBuilderAccess.Run);
        var module = assemblyBuilder.DefineDynamicModule("module1");

        var typeBuilder = module.DefineType("MyType", TypeAttributes.Public|TypeAttributes.Class);
        typeBuilder.AddInterfaceImplementation(typeof(IMyType));

        var builderField = typeBuilder.DefineField("_builder", typeof(StringBuilder), FieldAttributes.Static | FieldAttributes.Private);

        var methodBuilder = typeBuilder.DefineMethod(
            "UseStringBuilder",
            MethodAttributes.Public | MethodAttributes.Virtual,
            typeof(string),
            new Type[0]);

        var generator = methodBuilder.GetILGenerator();

        //this line causes InvalidProgramException, without this line it works
        generator.Emit(OpCodes.Ldsfld, builderField);

        generator.Emit(OpCodes.Ldstr, "Test");
        generator.Emit(OpCodes.Ret);


        var typeInfo = typeBuilder.CreateTypeInfo();
        var myType = typeInfo.AsType();

        IMyType instance = (IMyType)Activator.CreateInstance(myType);
        instance.UseStringBuilder();
我知道我没有使用StringBuilder来做任何事情,只是把它放在堆栈上,它将是null,因为它没有初始化,但是它是一个更大的程序的简化版本(为了重现问题),懒惰地初始化字段,所以我需要将它加载到堆栈上,以便检查它是否为null。然而,ldsfld指令在我执行任何操作之前使程序崩溃

此代码的工作版本的ILSPY如下所示:

// Fields
.field private static class [System.Runtime]System.Text.StringBuilder _builder

// Methods
.method public final hidebysig newslot virtual 
    instance string UseStringBuilder () cil managed 
{
    // Method begins at RVA 0x20ee
    // Code size 28 (0x1c)
    .maxstack 8

    IL_0000: ldsfld class [System.Runtime]System.Text.StringBuilder JsonicsTests.MyType::_builder
    IL_0005: brtrue.s IL_0011

    IL_0007: newobj instance void [System.Runtime]System.Text.StringBuilder::.ctor()
    IL_000c: stsfld class [System.Runtime]System.Text.StringBuilder JsonicsTests.MyType::_builder

    IL_0011: ldsfld class [System.Runtime]System.Text.StringBuilder JsonicsTests.MyType::_builder
    IL_0016: callvirt instance string [System.Runtime]System.Object::ToString()
    IL_001b: ret
}
使用Reflection.Emit创建和使用静态字段的正确方法是什么


如果相关的话,我正在linux上运行.net core 1.1。

堆栈不平衡有问题:在函数结束后在堆栈上留下一个值。尝试:

generator.Emit(OpCodes.Ldsfld, builderField);
generator.Emit(OpCodes.Pop); // Remove the value from the stack

这就解决了问题。我知道我遗漏了一些基本的东西。我的问题现在似乎有点低价值,我应该删除它吗?@trampster我觉得你的问题很有趣。堆栈必须为空/在生成的函数末尾必须有一个值(如果需要返回),这一事实非常重要,但在有关生成代码的教程中编写得不够强。