由于StackOverFlowException,DynamicMethod调用已终止

时间:2018-03-28 10:22:13

标签: c# dynamicmethod ilgenerator

我有这个类(简化示例)

public class Foo
{
    public object Bar(Type type)
    {
        return new object();
    }
}

我希望使用BarBar 的实例上调用DynamicMethod方法,如下所示:

MethodInfo methodInfo = typeof(Foo).GetMethod(nameof(Foo.Bar), new[] { typeof(Type) });
DynamicMethod method = new DynamicMethod("Dynamic Bar", 
                                         typeof(object), 
                                         new []{ typeof(Type) }, 
                                         typeof(Foo).Module);

ILGenerator ilGenerator = method.GetILGenerator();
ilGenerator.Emit(OpCodes.Ldarg_0);
ilGenerator.EmitCall(OpCodes.Call, method, null); // I feel like this is wrong...
ilGenerator.Emit(OpCodes.Ret);

Func<Type, object> func = (Func<Type, object>) method.CreateDelegate(typeof(Func<Type, object>));

// Attempt to call the function:
func(typeof(Foo));

但是,它不能按预期工作,而是使用

中止
  

由于StackOverFlowException,进程终止。

有人可以告诉我我做错了什么吗?这是参数的不匹配吗? 如何在Func的特定实例上调用Bar

1 个答案:

答案 0 :(得分:3)

ilGenerator.EmitCall(OpCodes.Call, method, null); // I feel like this is wrong...

您目前正在撰写 method;你可能打算在这里打电话给methodInfo。请注意,这需要static方法才能使用Call - 如果它是实例方法,您可能应该使用CallVirt。由于您没有传入Foo的实例,因此目前尚不清楚目标实例的来源;您需要将两个值加载到堆栈上以调用实例方法Foo.Bar(Type type) - 而您当前只加载一个。

显示Delegate.CreateDelegate用法:

var methodInfo = typeof(Foo).GetMethod(nameof(Foo.Bar), new[] { typeof(Type) });
var foo = new Foo();

// if Foo is known ahead of time:
var f1 = (Func<Type, object>)Delegate.CreateDelegate(
    typeof(Func<Type, object>), foo, methodInfo);

// if Foo is only known per-call:
var f2 = (Func<Foo, Type, object>)Delegate.CreateDelegate(
    typeof(Func<Foo, Type, object>), null, methodInfo);

Console.WriteLine(f1(typeof(string)));

Console.WriteLine(f2(foo, typeof(string)));