I'm trying to create a static field using Reflection.Emit.
However I get a InvalidProgramException when I try and load it.
The following code reproduces my problem.
The line: generator.Emit(OpCodes.Ldsfld, builderField); causes a InvalidProgramException, without this line the program runs fine and returns "Test" as expected
var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName(Guid.NewGuid().ToString()),
AssemblyBuilderAccess.Run);
var module = assemblyBuilder.DefineDynamicModule("module1");
var typeBuilder = module.DefineType("My.Type", TypeAttributes.Public|TypeAttributes.Class);
typeBuilder.AddInterfaceImplementation(typeof(IMyType));
var builderField = typeBuilder.DefineField("_builder", typeof(int), 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();
I know I'm not using the StringBuilder for anything just putting it on the stack, and that it will be null as it is not initialized, however it a simplified version of a larger program which lazy initializes the field, so I need to load it onto the stack so I can check it for null. However the ldsfld instruction crashes the program before I can do any of that.
ILSPY for a working version of this code looks like this:
// 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
}
What is the correct way to create and use a static field using Reflection.Emit?
I'm running on .net core 1.1 on linux if that is relevant.
Aucun commentaire:
Enregistrer un commentaire