Invoke Enumerable.Where (or other overloaded generic method) using reflection

守給你的承諾、 提交于 2021-02-04 15:47:20

问题


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!


回答1:


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>.




回答2:


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.



来源:https://stackoverflow.com/questions/7538462/invoke-enumerable-where-or-other-overloaded-generic-method-using-reflection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!