【问题标题】:How to pass Struct parameter when a Dynamic Method Invoke in C#?在 C# 中调用动态方法时如何传递 Struct 参数?
【发布时间】:2018-12-20 03:32:53
【问题描述】:

我在动态方法中传递结构参数时遇到问题。 这是我的代码:

public class Program
{
    static void Main(string[] args)
    {
        var DynamicAssembly = new AssemblyName();
        DynamicAssembly.Name = "DynamicTypes";
        AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(DynamicAssembly, AssemblyBuilderAccess.Run);
        ModuleBuilder mb = ab.DefineDynamicModule(DynamicAssembly.Name);
        TypeBuilder tb = mb.DefineType("Handler", TypeAttributes.Class | TypeAttributes.Public);
        MethodBuilder handler = tb.DefineMethod($"DynamicHandler",
            MethodAttributes.Public | MethodAttributes.Static,
           typeof(void),
           new Type[] { typeof(MyClass), typeof(MyStruct) });
        var ProcessMethod = typeof(Program).GetMethod(nameof(Process));
        ILGenerator il = handler.GetILGenerator();
        il.Emit(OpCodes.Nop);
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_1);
        il.EmitCall(OpCodes.Call, ProcessMethod, null);
        il.Emit(OpCodes.Nop);
        il.Emit(OpCodes.Ret);
        var DynamicType = tb.CreateType();
        MethodInfo methodInfo = DynamicType.GetMethod("DynamicHandler");
        int i = 100;
        while (true)
        {
            i++;
            MyClass a = new MyClass()
            {
                a = i,
            };
            MyStruct b = new MyStruct()
            {
                b = i,
            };
            methodInfo.Invoke(null, new object[] { a, b });
            Thread.Sleep(3000);
        }
    }
    public static void Process(object arg1, object arg2)
    {
        Console.WriteLine($"arg1:{arg1} arg2:{arg2}");
    }
}
public struct MyStruct
{
    public int a;
    public int b;
}
public class MyClass
{
    public int a;
    public int b;
}

当我将代码运行到Process 方法参数arg2 时发现'FatalExecutionEngineError' 无法读取内存。

但是如果我将第二个参数更改为MyStruct 就像

    public static void Process(object arg1,MyStruct arg2)
    {
        Console.WriteLine($"arg1:{arg1} arg2:{arg2}");
    }

它工作正常,但这不是我想要的。

我认为我的 IL 代码不正确,但我不知道它在哪里。

【问题讨论】:

    标签: c# emit dynamicmethod


    【解决方案1】:

    您必须在 MyStruct 上调用 OpCodes.Box 才能将其作为 object 作为参数传递给方法。

    您也无需致电OpCodes.Nopeither。 所以基本上你的代码应该是这样的→

    il.Emit(OpCodes.Ldarg_0);
    il.Emit(OpCodes.Ldarg_1);
    il.Emit(OpCodes.Box, typeof(MyStruct));
    //Rest is the same
    

    【讨论】:

    • 感谢您的回答。我刚才试过了,但是当代码运行到methodInfo.Invoke(null, new object[] { a, b });'System.Reflection.TargetInvocationException'时抛出一个异常,IninterException is BadImageFormatException:类标签不正确。
    • @BigDream 可能是 x32 - x64 位不匹配。请检查您的项目的目标平台并相应地编译它们。据我了解,由于您使用的是动态程序集,因此您不妨使用 Assembly.Load 加载外部 .dll
    • 我尝试将项目更改为'AnyCpu','x86'和'x64'三个patform。看起来它们之间没有区别。它仍然像以前一样抛出异常。
    • 这是一个测试项目,所以里面没有外部 .dll。
    • @BigDream,我的本地测试代码编译没有任何问题。你能给我更多的见解吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 1970-01-01
    • 2015-09-23
    • 1970-01-01
    • 2017-05-11
    • 1970-01-01
    相关资源
    最近更新 更多