There are 2 overloads (or method signatures) of the "Where" method in Enumerable class:
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);
}
So
var where = typeof(Enumerable).GetMethod("Where")
throws an exception stating an ambiguous match because, of course, there is more than one method with the name "Where", so I tried to differentiate by the parameters:
var types = new[] {
typeof(IEnumerable<>),
typeof(Func<,>)};
var where = typeof(Enumerable).GetMethod("Where", types);
This however doesn't match either of the method signatures, and I'm not sure why.
Generalized question: How do you invoke an overloaded generic method via reflection without iterating over all the methods in the class w/ the same name (i.e., using System.Type.GetMethod(System.String, System.Type[])?
Please help me fix it! Thanks!
The first step to dynamically invoking a generic method with reflection is to use reflection to get access to the MethodInfo of the generic method. To do that simply do this: var methodInfo = typeof(ClassWithGenericMethod). GetMethod("MethodName");
To call a generic method, you need to provide types that will be used during the method invocation. Those types can be passed as an instance of NType objects initialized with particular . NET types.
You can't accomplish this with only GetMethod()
because it has limitations with generics. This is how you would do it with GetMethod()
properly.
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);
The best way is to just iterate over members
since it already contains both MethodInfo
definitions for Where<TSource>
.
You might be interested to see a code snippet I posted in this other answer:
It's a more general way to get any generic method via an extension method, with clean syntax that looks like:
var where = typeof(Enumerable).GetMethod(
"Where",
typeof(IQueryable<Refl.T1>),
typeof(Expression<Func<Refl.T1, bool>>
);
Notice the Refl.T1
that takes the place of a generic type parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With