5

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
  • 10,450
  • 21
  • 81
  • 152

3 Answers3

6
var foo = enumerableType.GetMethods(BindingFlags.Static | BindingFlags.Public)
            .First(m => m.Name == "Any" && m.GetParameters().Count() == 2);
EZI
  • 14,888
  • 2
  • 26
  • 32
  • 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
  • 52,041
  • 10
  • 126
  • 179
0

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
  • 1,509
  • 16
  • 23