使用反射调用Enumerable.Where(或其他重载的泛型方法)

时间:2011-09-24 10:34:52

标签: c# .net reflection extension-methods

Enumerable类中的“Where”方法有2个重载(或方法签名):

namespace System.Linq {
    public static class Enumerable {
        public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate);
        public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate);
    }

所以

var where = typeof(Enumerable).GetMethod("Where") 

抛出异常表明模糊匹配,因为当然,有多个名称为“Where”的方法,所以我尝试通过参数进行区分:

var types = new[] { 
    typeof(IEnumerable<>), 
    typeof(Func<,>)};
var where = typeof(Enumerable).GetMethod("Where", types);

然而,这与任何方法签名都不匹配,我不确定原因。

广义问题:如何通过反射调用重载的泛型方法,而不迭代具有相同名称的类中的所有方法(即使用System.Type.GetMethod(System.String,System.Type []) ?

请帮我修理一下!谢谢!

2 个答案:

答案 0 :(得分:5)

仅使用GetMethod()无法完成此操作,因为它对泛型有限制。这就是你如何正确地使用GetMethod()

Type enumerableType = typeof(Enumerable);
MemberInfo[] members = enumerableType.GetMember("Where*");
MethodInfo whereDef = (MethodInfo)members[0]; // Where<TSource>(IEnumerable<TSource, Func<TSource,Boolean>)
Type TSource = whereDef.GetGenericArguments()[0]; // TSource is the only generic argument
Type[] types = { typeof(IEnumerable<>).MakeGenericType(TSource), typeof(Func<,>).MakeGenericType(TSource, typeof(Boolean)) };
MethodInfo method = enumerableType.GetMethod("Where", types);

最好的方法是迭代members,因为它已包含MethodInfo的{​​{1}}个定义。

答案 1 :(得分:1)

您可能有兴趣看到我在其他answer中发布的代码段:

这是通过扩展方法获取任何泛型方法的更通用方法,其语法如下:

var where = typeof(Enumerable).GetMethod(
  "Where", 
  typeof(IQueryable<Refl.T1>), 
  typeof(Expression<Func<Refl.T1, bool>>
);

注意取代泛型类型参数的Refl.T1