【问题标题】:C# MSIL call method and pass an object[]C# MSIL 调用方法并传递一个对象[]
【发布时间】:2018-08-12 10:46:02
【问题描述】:

我想使用反射发射依赖将 C# 中的方法转换为 MSIL 代码。

我尝试转换的方法是转换方法:

public class AClass
{
    public string Transformation(string a, string b, string c)
    {
        return new AnotherClass().Method(new object[] { a, b, c });
    }
}

public class AnotherClass
{
    public string Method(params object[] objs)
    {
        return "AAA";
    }
}

所以基本上创建一个类的实例并使用一个新对象[]调用一个方法函数,该对象将处理所有传递给它的参数。

当我查看 IlSpy 时,我有这个:

.method public hidebysig 
instance string Transformation (
    string a,
    string b,
    string c
) cil managed 
{
// Method begins at RVA 0x20d0
// Code size 34 (0x22)
.maxstack 5
.locals init (
    [0] string
)

IL_0000: nop
IL_0001: newobj instance void ConsoleApp1.AnotherClass::.ctor()
IL_0006: ldc.i4.3
IL_0007: newarr [mscorlib]System.Object
IL_000c: dup
IL_000d: ldc.i4.0
IL_000e: ldarg.1
IL_000f: stelem.ref
IL_0010: dup
IL_0011: ldc.i4.1
IL_0012: ldarg.2
IL_0013: stelem.ref
IL_0014: dup
IL_0015: ldc.i4.2
IL_0016: ldarg.3
IL_0017: stelem.ref
IL_0018: call instance string ConsoleApp1.AnotherClass::Method(object[])
IL_001d: stloc.0
IL_001e: br.s IL_0020

IL_0020: ldloc.0
IL_0021: ret
} // end of method AClass::Transformation

并尝试创建一个函数来表示:

 public static void CallFucntionThroughIl(ILGenerator il, Type[] parameters, MethodInfo method)
    {
        il.Emit(OpCodes.Nop);

        il.Emit(OpCodes.Newobj, typeof(AnotherClass).GetConstructor(Type.EmptyTypes));

        il.Emit(OpCodes.Ldc_I4, parameters.Length);

        il.Emit(OpCodes.Newarr, typeof(object));

        for (int i = 0; i < parameters.Length; i++)
        {
            il.Emit(OpCodes.Dup);
            il.Emit(OpCodes.Ldc_I4, i);
            il.Emit(OpCodes.Ldarg, i + 1);
            il.Emit(OpCodes.Stelem_Ref);
        }

        il.EmitCall(OpCodes.Callvirt,
            typeof(AnotherClass).GetMethod("Method").MakeGenericMethod(method.ReturnType),
            new Type[] { typeof(object[]) });

        il.Emit(OpCodes.Stloc_0);

        var label = il.DefineLabel();

        il.Emit(OpCodes.Br_S, label);

        il.MarkLabel(label);
        il.Emit(OpCodes.Ldloc_0);

        il.Emit(OpCodes.Ret);
    }

但有时我不知道自己做错了什么,调试时遇到的唯一错误是: System.InvalidProgramException: '公共语言运行时检测到无效程序。'

目标只是复制“转换”函数所做的事情,获取所有参数并将其传递给对象 [] 调用参数中包含该对象 [] 的方法并返回其他方法返回的内容。

注意:转换函数并不总是会接收3个字符串,也可以是其他对象。

【问题讨论】:

  • 你为什么打电话给MakeGenericMethod?我在您的代码中看不到任何泛型。但话又说回来,你没有显示不在示例 IL 中的类 RestInPiece
  • 抱歉,RestInPiece 类打错了

标签: c# reflection cil reflection.emit gac-msil


【解决方案1】:

挖了很久:

在 Nop 之后缺少 DeclareLocal:

il.Emit(OpCodes.Nop);
il.DeclareLocal(typeof(object[]));

尝试分配给本地不存在的变量时可能会崩溃。

il.Emit(OpCodes.Stloc_0);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 2011-05-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多