Reflection.Emitを使用して静的フィールドを作成しようとしています。Reflection.Emitを使用して静的フィールドを作成する方法
しかし、私はそれをロードしようとするとInvalidProgramExceptionが発生します。
次のコードは私の問題を再現します。
ライン:
generator.Emit(OpCodes.Ldsfld, builderField);
は、次の例外が発生します。この行のない
Unhandled Exception: System.InvalidProgramException: Common Language Runtime detected an invalid program.
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になります初期化されていませんが、フィールドを初期化するより大きなプログラムの単純化されたバージョンです(問題を再現するために)ので、ヌルをチェックできるようにスタックにロードする必要があります。しかし、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を実行していますが、これは関連しています。
それを修正しました。私は欠けていた何か基本的なものがあることを知っていた。私の質問は、現在価値が低いようですが、私はそれを削除すべきですか? – trampster
@trampsterあなたの質問は非常に興味深いと思います。スタックが空でなければならない/生成された関数の最後に単一の値(返す必要がある場合)がなければならないという事実は、コード生成に関するチュートリアルでは強く書かれていない非常に重要なことです。 – xanatos