6

I'm trying to build an Expression that makes a call to LINQ's Any() method, and I can't seem to find the right arguments to pass to Type.GetMethod().

From the docs, it looks like Any() is implemented as a member of the Enumerable class, and that seems to work, because this shows to methods named "Any":

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

And when I as for the method named "Any", I get an AmbiguousMatchException.

There are two Any() methods, in Enumerable, one takes one parameter an IEnumerable, and the other takes an IEnumerable and a Func. I want the second, and theoretically, all I need to do is to pass an array containing the two types:

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

But this is always returning null.

What am I doing wrong?

Jeff Dege
  • 11,190
  • 22
  • 96
  • 165

4 Answers4

6
var foo = enumerableType.GetMethods(BindingFlags.Static | BindingFlags.Public)
            .First(m => m.Name == "Any" && m.GetParameters().Count() == 2);
EZI
  • 15,209
  • 2
  • 27
  • 33
  • 2
    `m.GetParameters().Count() == 2` probably not very safe for portability (eg. migration to a higher version of the framework). You may want to check what the actual parameters of the method are. – Caramiriel Aug 05 '14 at 20:09
  • I don't know why I didn't think of this. I was using LINQ in my example, to filter out the "Any" methods. I was just stuck on somehow passing the right parameters into GetMethod(). – Jeff Dege Aug 05 '14 at 22:03
5

If you want to specifically ensure that you're matching the overload that takes IEnumerable<> and Func<,> parameters, you can use the following (adapted from 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();
Community
  • 1
  • 1
Douglas
  • 53,759
  • 13
  • 140
  • 188
1

Thanks to @JonSkeet for pointing me in the right direction, here's a couple of one liners:

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)));
Tod
  • 2,070
  • 21
  • 27
-1

As the Enumerable.Any is a method that is accessible at compile time, it's possible to use the following simple and type safe approach based on delegate:

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

You are free to match the signature of delegate to whatever overload of method you want to get MethodInfo for.

Sargis G
  • 1
  • 1
  • Read the question well and read a bit between the lines. It's clear that they want to find the method info based on a string "Any". – Gert Arnold Oct 15 '22 at 21:27
  • @GertArnold, I don't agree with you. I think the main point of the question is how to get `MethodInfo` for `Enumerable.Any` method, I don't see in the words of author the requirement to get it based on the string "Any". – Sargis G Oct 15 '22 at 21:55
  • For what purpose do you think they want to find the method info? – Gert Arnold Oct 15 '22 at 22:11
  • Why are you asking? Maybe you hint to the point that the author write about 'trying to build an Expression'. And maybe you hint that it is not known at compile time for which method a 'MethodInfo' is needed. If so, I think it is a wrong conclusion. – Sargis G Oct 15 '22 at 22:42
  • The point is that if *at compile time* they know exactly which method they need there's no point in trying to find it by a string, which they do nevertheless. – Gert Arnold Oct 16 '22 at 08:50