关于c#:Reflection.Emit:如何可靠地将MethodBuilder转换为RuntimeMethodInfo?

Reflection.Emit: How to convert MethodBuilder to RuntimeMethodInfo reliably?

动态生成类型并调用typebuilder.createType后,我希望创建一个指向新类型中的方法的委托。但是如果我使用类似代码

1
2
3
loadedType = typeBuilder.CreateType();
myDelegate = (MyDelegate)Delegate.CreateDelegate(
                                  typeof(MyDelegate), methodBuilder);

将methodbuilder重用为methodinfo时,我得到异常"methodinfo必须是runtimemethodinfo"。现在通常我可以用

1
2
MethodInfo mi = loadedType.GetMethod(methodBuilder.Name);
myDelegate = (MyDelegate)Delegate.CreateDelegate(typeof(MyDelegate), mi);

但是我的类可能包含几个同名的重载方法。如何确保我找到正确的答案?方法是否有一些我可以在loadedType中查找的持久标识符?

更新:好的,这是我用来重新获取MethodInfo的。我只是希望我能确定它在任何情况下都能起作用。

1
2
3
4
5
6
7
8
9
10
private static MethodInfo ReacquireMethod(Type type, MethodInfo method)
{
    BindingFlags flags = BindingFlags.DeclaredOnly;
    flags |= (method.IsPublic ? BindingFlags.Public : BindingFlags.NonPublic);
    flags |= (method.IsStatic ? BindingFlags.Static : BindingFlags.Instance);
    MethodInfo m = type.GetMethod(method.Name, flags, null,
                                          ParameterTypes(method), null);
    Debug.Assert(m != null);
    return m;
}


据我所知,没有持久的共享标识符。

方法的重载是通过参数列表来区分的,所以我猜您需要在methodBuilder上调用GetParameters,然后将返回的ParameterInfo[]数组转换为Type[]数组,以传递给适当的GetMethod重载:

1
2
3
MethodInfo mi = loadedType.GetMethod(
    methodBuilder.Name,
    methodBuilder.GetParameters().Select(p => p.ParameterType).ToArray());


需要使用获取类型数组的getMethod重载。方法重载由传递给它们的参数选择进行绑定。由于在通过反射获取方法的元数据时实际上没有调用方法,因此必须提供类型对象的有序数组才能获得正确的MethodInfo对象:

type.getmethod方法(字符串,类型[])

用途:

1
2
3
4
5
6
7
8
MethodInfo mi = loadedType.GetMethod(
    methodBuilder.Name,
    new[]
    {
        typeof(string),
        typeof(int)
    }
);

assiming methodbuilder.name是"mymethod",它将绑定以下内容:

1
public <returnType> MyMethod(string param1, int param2);

请记住,返回类型不是方法签名的一部分,只有方法名及其参数类型是。