获取LINQ's Any()方法的MethodInfo

本文关键字:方法 MethodInfo Any LINQ 获取 | 更新日期: 2023-09-27 18:16:27

我试图建立一个表达式,使调用LINQ的Any()方法,我似乎找不到正确的参数传递给Type.GetMethod()。

从文档来看,Any()似乎是作为Enumerable类的成员实现的,这似乎是有效的,因为它显示了名为"Any"的方法:

var enumerableType = typeof (Enumerable);
var foo = enumerableType.GetMethods().Where(m => m.Name == "Any").ToList();

当我使用名为"Any"的方法时,我得到一个AmbiguousMatchException。

在Enumerable中有两个Any()方法,一个接受IEnumerable参数,另一个接受IEnumerable参数和Func参数。我需要第二种类型,理论上,我所需要做的就是传递一个包含这两种类型的数组:

var bar = enumerableType.GetMethod("Any", new[] { typeof(IEnumerable<>), typeof(Func<,>) });

但是这总是返回null。

我做错了什么?

获取LINQ's Any()方法的MethodInfo

var foo = enumerableType.GetMethods(BindingFlags.Static | BindingFlags.Public)
            .First(m => m.Name == "Any" && m.GetParameters().Count() == 2);

如果您想明确地确保您匹配了接受IEnumerable<>Func<,>参数的重载,您可以使用以下方法(改编自此回答):

var enumerableType = typeof(Enumerable);
var bar =
(
    from m in enumerableType.GetMethods(BindingFlags.Static | BindingFlags.Public)
    where m.Name == "Any"
    let p = m.GetParameters()
    where p.Length == 2
        && p[0].ParameterType.IsGenericType
        && p[0].ParameterType.GetGenericTypeDefinition() == typeof(IEnumerable<>)
        && p[1].ParameterType.IsGenericType
        && p[1].ParameterType.GetGenericTypeDefinition() == typeof(Func<,>)
    select m
).SingleOrDefault();

感谢@JonSkeet为我指出了正确的方向,这里有几个一行:

var any = typeof(Enumerable).GetMethods().FirstOrDefault(m => m.Name == "Any" && m.IsGenericMethodDefinition && m.GetParameters().Length == 1 && m.GetParameters()[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(m.GetGenericArguments()[0]));
var anyWhere = typeof(Enumerable).GetMethods().FirstOrDefault(m => m.Name == "Any" && m.IsGenericMethodDefinition && m.GetParameters().Length == 2 && m.GetParameters()[0].ParameterType == typeof(IEnumerable<>).MakeGenericType(m.GetGenericArguments()[0]) && m.GetParameters()[1].ParameterType == typeof(Func<,>).MakeGenericType(m.GetGenericArguments()[0], typeof(bool)));

由于Enumerable.Any是在编译时可访问的方法,因此可以使用以下基于delegate的简单且类型安全的方法:

var anyMethodInfo = ((Func<IEnumerable<object>, Func<object, bool>, bool>)Enumerable.Any)
    .Method.GetGenericMethodDefinition();

您可以自由地将delegate的签名匹配到您想要获得MethodInfo的方法的任何重载