如何在非泛型的.NET类型上获取泛型方法的MethodInfo?

8

我有一个小问题,就是我不知道在Type.GetMethod中传递哪些参数才能够获取非泛型类型上的泛型方法的MethodInfo。 具体来说,我有以下类型定义:

public static class A
{
  public static B F<T>(bool dummy)
  {
  }
  public static B F<T>(IEnumerable<T> arg)
  {
  ...
  }
}

我已经尝试了几种Type.GetMethod的方法,但是没有一种能够返回F方法的MethodInfo。

我知道可以调用Type.GetMethods甚至Type.FindMember,但我只对Type.GetMethod感兴趣。

有什么想法吗?

谢谢。

编辑

实际上,我的代码有点复杂。这个泛型方法是重载的,所以我不能只使用函数名来调用Type.GetMethod。 我尝试了这些变体:

typeof(A).GetMethod("F", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
typeof(A).GetMethod("F`1", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
typeof(A).GetMethod("F[T]", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
typeof(A).GetMethod("F[[T]]", BindingFlags.Static | BindingFlags.Public, null, new Type[]{ typeof(IEnumerable<>) }, null)
2个回答

9
问题在于您传递给GetMethod的IEnumerable<>参数没有特化。它实际上是一个IEnumerable,其中T由您要检索的方法指定。但是,我们无法通过MethodInfo.GetGenericArguments()获取T,因为我们还在尝试检索它。
不幸的是,这就是反射API的短板所在。没有Type.GetMethod()重载允许您区分重载方法和泛型方法之间的差异。
因此,您必须使用Type.GetMethods()并使用自己选择的谓词来过滤结果。要获取您感兴趣的方法,可以执行以下操作。
void getMethod()
{
    typeof(A).GetMethods().Where(m =>
        m.IsGenericMethod &&
        m.GetParameters()[0].ParameterType.GetGenericTypeDefinition()
            == typeof(IEnumerable<>));
}

注意:我没有验证GetGenericTypeDefinition()调用是否必要,你可能可以省略它。思路是将类型A<T>转换为A<>,但运行时可能已经以该形式提供给您。


5

(根据问题澄清更新):

使用GetMethod(例如一行)无法获得对该方法的句柄,因为定义该方法的通用数据直到我们检查该方法后才可用。

MethodInfo[] methods = typeof(A).GetMethods(BindingFlags.Static | BindingFlags.Public);
MethodInfo genericMethod = methods.Where(m=>m.IsGenericMethod).First(m=>m.ContainsGenericParameters);
genericMethod = genericMethod.GetGenericMethodDefinition();
  1. 获取方法
  2. 找到具有泛型参数的方法(假设您只有一个 - 如果添加了多个,则需要更加强大)
  3. 获取泛型方法信息

1
谢谢,但是我在问题中有些误导了。我已经更正了以使其更准确。 - mark
谢谢,但是正如我在问题中提到的那样,我知道如何使用GetMethods或FindMember来完成它。我特别感兴趣的是GetMethod,因为它也应该能够完成这项工作,但实际上却不能,这让我很困扰。 - mark
@Mark 没有办法做到这一点,因为在我们有要检查的方法之前,定义方法的通用数据是不可用的。 - Rex M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接