C# - Reflection.Emit : 返回被调用方法的结果。

问题描述 投票:0回答:1

在一个DynamicMethod中,我试图调用一个想要一个对象数组的方法来返回给定数组的长度。目前,我的方法应该从DynamicMethod中调用,如下所示。

public static int Test(Object[] args)
{
    Console.WriteLine(args.Length);
    return args.Length;
}

DynamicMethod的创建过程如下:

(Object数组的创建采用了下面的方法) 所以回答)

public static DynamicMethod GetDM()
{ 
    var returnType = typeof(int);
    var paramTypes = new Type[]{typeof(string), typeof(bool)};

    var method = new DynamicMethod(
        "",
        returnType,
        paramTypes,
        false
    );
    var il = method.GetILGenerator();

    // Save parameters in an object array
    il.Emit(OpCodes.Ldc_I4_S, paramTypes.Length);
    il.Emit(OpCodes.Newarr, typeof(Object));
    il.Emit(OpCodes.Dup);

    for (int i = 0; i < paramTypes.Length; i++)
    {
        Type type = paramTypes[i];

        il.Emit(OpCodes.Ldc_I4, i);
        il.Emit(OpCodes.Ldarg, i);
        if (type.IsValueType) { il.Emit(OpCodes.Box, type); }
        il.Emit(OpCodes.Stelem_Ref);
        il.Emit(OpCodes.Dup);
    }

    // Call method and get the length of the array
    // How do I return the result of the called method?
    var callMethod = typeof(Program).GetMethod("Test", (BindingFlags)(-1));
    il.Emit(OpCodes.Call, callMethod);

    il.Emit(OpCodes.Ret);

    return method;
}

通过下面的方法,我检查了功能。

public static void Main(string[] args)
{
    var method = GetDM();
    var result = method.Invoke(null, new Object[]{"Test 1234", true});
    Console.WriteLine(result); // Should be 2
}

当我运行主方法时,我得到 System.Reflection.TargetInvocationException. 谁能帮我解决如何返回被调用方法所返回的值?下面是一个 联系 到一个dotnetfiddle来看看我的问题。

c# reflection reflection.emit dynamicmethod
1个回答
0
投票

for 循环,你在堆栈上有两次构造的对象数组(因 Dup 调用)。) 这些数组引用中只有一个被 Call 所以在方法结束时,你将在堆栈中多了一个数组引用。

要纠正这个问题,请删除第一个Dup,并将第二个Dup移到循环体的头部。

public static DynamicMethod GetDM() {  
    var returnType = typeof(int);
    var paramTypes = new Type[]{typeof(string), typeof(bool)};

    var method = new DynamicMethod(
        "",
        returnType,
        paramTypes,
        false
    );
    var il = method.GetILGenerator();

    // Save parameters in an object array
    il.Emit(OpCodes.Ldc_I4_S, paramTypes.Length);
    il.Emit(OpCodes.Newarr, typeof(Object));

    for (int i = 0; i < paramTypes.Length; i++)
    {
        Type type = paramTypes[i];

        il.Emit(OpCodes.Dup);
        il.Emit(OpCodes.Ldc_I4, i);
        il.Emit(OpCodes.Ldarg, i);
        if (type.IsValueType) { il.Emit(OpCodes.Box, type); }
        il.Emit(OpCodes.Stelem_Ref);
    }

    // Call method and get the length of the array
    // How do I return the result of the called method?
    var callMethod = typeof(Program).GetMethod("Test", (BindingFlags)(-1));
    il.Emit(OpCodes.Call, callMethod);

    il.Emit(OpCodes.Ret);

    return method;
}
© www.soinside.com 2019 - 2024. All rights reserved.