Вызвать Enumerable.Where (или другой перегруженный универсальный метод), используя отражение - PullRequest
4 голосов
/ 24 сентября 2011

Существует 2 перегрузки (или сигнатуры методов) метода "Where" в классе Enumerable:

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") 

выдает исключение, указывающее на неоднозначное совпадение, потому что,Конечно, существует более одного метода с именем «Где», поэтому я попытался провести различие по параметрам:

var types = new[] { 
    typeof(IEnumerable<>), 
    typeof(Func<,>)};
var where = typeof(Enumerable).GetMethod("Where", types);

Это, однако, не соответствует ни одной из сигнатур метода, и яне знаю, почему.

Обобщенный вопрос: как вызвать перегруженный универсальный метод с помощью отражения, не повторяя все методы в классе с одним и тем же именем (т. е. используя System.Type.GetMethod (System.String, System.Type [])?

Пожалуйста, помогите мне исправить это! Спасибо!

Ответы [ 2 ]

5 голосов
/ 24 сентября 2011

Вы не можете сделать это только с GetMethod(), потому что у него есть ограничения с дженериками. Вот как вы бы правильно сделали это с GetMethod().

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

Лучший способ - просто перебрать members, поскольку он уже содержит оба определения MethodInfo для Where<TSource>.

1 голос
/ 29 февраля 2012

Возможно, вам будет интересно увидеть фрагмент кода, который я разместил в этом другом ответе :

Это более общий способ получения любого универсального метода через метод расширения с чистым синтаксисом, который выглядит следующим образом:

var where = typeof(Enumerable).GetMethod(
  "Where", 
  typeof(IQueryable<Refl.T1>), 
  typeof(Expression<Func<Refl.T1, bool>>
);

Обратите внимание на Refl.T1, который занимает место параметра универсального типа.

...