'How to translate this IL Code to Reflection.Emit in C#?
This is the IL code I'm trying to translate to C# without succes:
.assembly _
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = (
01 00 08 00 00 00 00 00
)
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = (
01 00 01 00 54 02 16 57 72 61 70 4e 6f 6e 45 78
63 65 70 74 69 6f 6e 54 68 72 6f 77 73 01
)
.custom instance void [mscorlib]System.Diagnostics.DebuggableAttribute::.ctor(valuetype [mscorlib]System.Diagnostics.DebuggableAttribute/DebuggingModes) = (
01 00 02 00 00 00 00 00
)
.hash algorithm 0x00008004 // SHA1
.ver 0:0:0:0
}
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi MYCLASS
extends [mscorlib]System.Object
{
// Fields
.field private object _myTextBlock
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Methods
.method public specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 23 (0x17)
.maxstack 8
// sequence point: hidden
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ldarg.0
IL_0007: newobj instance void [mscorlib]System.Object::.ctor()
IL_000c: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_0011: call instance void MYCLASS::set_myTextBlock(object)
IL_0016: ret
} // end of method MYCLASS::.ctor
.method public specialname
instance object get_myTextBlock () cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2068
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldfld object MYCLASS::_myTextBlock
IL_0006: ret
} // end of method MYCLASS::get_myTextBlock
.method public specialname
instance void set_myTextBlock (
object AutoPropertyValue
) cil managed
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Method begins at RVA 0x2070
// Code size 13 (0xd)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldarg.1
IL_0002: call object [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::GetObjectValue(object)
IL_0007: stfld object MYCLASS::_myTextBlock
IL_000c: ret
} // end of method MYCLASS::set_myTextBlock
// Properties
.property instance object myTextBlock()
{
.get instance object MYCLASS::get_myTextBlock()
.set instance void MYCLASS::set_myTextBlock(object)
}
} // end of class MYCLASS
This is what I'm translating from:
public class MYCLASS : object
{
public object myTextBlock { get; set; } = new object();
}
This is what I have so far that is working but is not inheriting the class or initialising the properties:
public Type CreateClass(string className, Dictionary<string, Type> properties)
{
AssemblyName myAsmName = new AssemblyName("RoadAssembly");
AssemblyBuilder myAssembly = myAssembly.DefineDynamicAssembly(myAsmName, AssemblyBuilderAccess.Run);
ModuleBuilder myModule = myAssembly.DefineDynamicModule("RoadAssembly");
TypeBuilder myType = myModule.DefineType(className, TypeAttributes.Public);
myType.DefineDefaultConstructor(MethodAttributes.Public);
foreach (var o in properties)
{
PropertyBuilder prop = myType.DefineProperty(o.Key, PropertyAttributes.HasDefault, o.Value, null/* TODO Change to default(_) if this is not a reference type */);
FieldBuilder field = myType.DefineField("_" + o.Key, o.Value, FieldAttributes.Private);
MethodBuilder getter = myType.DefineMethod("get_" + o.Key, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, o.Value, Type.EmptyTypes);
ILGenerator getterIL = getter.GetILGenerator();
getterIL.Emit(OpCodes.Ldarg_0);
getterIL.Emit(OpCodes.Ldfld, field);
getterIL.Emit(OpCodes.Ret);
MethodBuilder setter = myType.DefineMethod("set_" + o.Key, MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig, null/* TODO Change to default(_) if this is not a reference type */, new Type[] { o.Value });
ILGenerator setterIL = setter.GetILGenerator();
setterIL.Emit(OpCodes.Ldarg_0);
setterIL.Emit(OpCodes.Ldarg_1);
setterIL.Emit(OpCodes.Stfld, field);
setterIL.Emit(OpCodes.Ret);
prop.SetGetMethod(getter);
prop.SetSetMethod(setter);
}
return myType.CreateType();
}
I have tried making a constructor for the type to translate the "New Object" part with no success, this is my attempted constructor:
{
ConstructorBuilder cBuilder = myType.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { o.Value });
ConstructorInfo conObj = typeof(object).GetConstructor(new Type[0] { });
ILGenerator cil = cBuilder.GetILGenerator();
cil.Emit(OpCodes.Ldarg_0);
cil.Emit(OpCodes.Newobj, conObj);
cil.Emit(OpCodes.Stfld, field);
cil.Emit(OpCodes.Ldarg_0);
cil.Emit(OpCodes.Call, conObj);
cil.Emit(OpCodes.Ret);
}
I do not understand how the OpCodes work or where I have to place this constructor in my function so I can properly initialise the objects of this class when I create an object of this class.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|
