是否获取LINQ的Any()方法的MethodInfo?

ht4b089n  于 2022-12-06  发布在  其他
关注(0)|答案(4)|浏览(127)

我试图构建一个调用LINQ的Any()方法的表达式,但似乎找不到传递给Type.GetMethod()的正确参数。
从文档中看,Any()似乎是作为Enumerable类的成员实现的,这似乎是可行的,因为这显示了名为“Any”的方法:

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

当我使用名为“Any”的方法时,我会得到一个AmbiguousMatchException。
有两个Any()方法,在Enumerable中,一个接受一个参数IEnumerable,另一个接受一个IEnumerable和一个Func。我想要第二个,理论上,我所需要做的就是传递一个包含这两个类型的数组:

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

但这总是返回null。
我做错了什么?

wlp8pajw

wlp8pajw1#

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

goqiplq22#

如果要特别确保匹配采用IEnumerable<>Func<,>参数的重载,可以使用以下代码(改编自this answer):

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();
agyaoht7

agyaoht73#

感谢@JonSkeet为我指出了right direction,这里有几句俏皮话:

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)));
osh3o9ms

osh3o9ms4#

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

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

您可以自由地将委托的签名与要获取MethodInfo的方法的任何重载进行匹配。

相关问题