如何将此 IL 代码转换为 C# 中的 Reflection.Emit?

发布于 2025-01-12 17:05:00 字数 5708 浏览 0 评论 0原文

这是我试图将其转换为 C# 的 IL 代码,但没有成功:

    .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

这就是我要翻译的代码:

public class MYCLASS : object
{
    public object myTextBlock { get; set; } = new object();
}

这是我到目前为止正在运行的代码,但没有继承该类或初始化属性:

    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();
}

我已经尝试过用于转换“新对象”部分但没有成功的类型的构造函数,这是我尝试的构造函数:

{
    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);
}

我不明白 OpCode 是如何工作的,也不明白我必须将此构造函数放在函数中的位置,以便我可以正确初始化当我创建一个对象时这个类这堂课。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文