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

ldp*_*ldp 4 .net c# 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);
    }
Run Code Online (Sandbox Code Playgroud)

所以

var where = typeof(Enumerable).GetMethod("Where") 
Run Code Online (Sandbox Code Playgroud)

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

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

然而,这与任何一种方法签名都不匹配,我不知道为什么.

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

请帮我解决一下!谢谢!

Dav*_*son 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);
Run Code Online (Sandbox Code Playgroud)

最好的方法是迭代,members因为它已经包含两个MethodInfo定义Where<TSource>.