2016-12-07 6 views
-1

Я начал этот метод расширения для удовольствия, но теперь я считаю себя застрял в ней,Как работать с членами типа Generic в методе расширения?

На самом деле я хочу, чтобы создать метод расширения для расширения LINQ, этот метод будет выглядеть следующим образом:

books.In(b => b.Id, 1,2,3,4,5); 

Это будет возвращать книги с диапазоном Id во втором params[],

это также можно сделать так:

books.In(b => b.Title, "t1","t2","t3","t4","t5"); 

То, что я придумал этот метод (я только знал о дереве выражений сегодня!):

public static List<TEntity> In<TEntity, TMember>(this List<TEntity> list, 
      Expression<Func<TEntity, TMember>> identifier, params TMember[] keys) 
     { 
      Type t = typeof(TEntity); //How to use reflection here? 

      List<TEntity> myList = list.Where(m => keys.Contains(m.)); 
      return myList; 
     } 

моей проблема заключается в том, чтобы получить доступ к непатентованным членам класса: то есть m.Id или m.Title из выражения identifier? Могу ли я использовать отражение, чтобы это произошло?

+4

'идентификатор' должен быть' Func ', если вы хотите использовать' Enumerable.Where' для фильтрации. Тогда это просто «list.Where» (m => keys.Contains (идентификатор (m)) », хотя вы можете захотеть создать набор ключей, чтобы сделать поиск более эффективным. – Lee

+2

Если намерение заключается в том, чтобы это было переведено в SQL, тогда вы должны использовать 'IQueryable' вместо' List'. – juharr

ответ

2

Это должно сделать:

public static IEnumerable<TEnitity> In<TEnitity, TMember>(
    this IEnumerable<TEnitity> source, 
    Func<TEnitity, TMember> projector, IEnumerable<TMember> validCases) 
{ 
    var validSet = new HashSet<TMember>(validCases); 
    return source.Where(s => validSet.Contains(projector(s))); 
} 

Или выполнить exaclty с подписью вы предлагаете:

public static IEnumerable<TEntity> In<TEntity, TMember>(
    this IEnumerable<TEntity> source, 
    Func<TEntity, TMember> projector, params TMember[] validCases) 
{ 
    var validSet = new HashSet<TMember>(validCases); 
    return source.Where(s => validSet.Contains(projector(s))); 
} 

О, почему я возвращаюсь IEnumerable<T> вместо List<T> рассуждения дешево обобщение; если потребитель хочет вернуть список, тогда ему просто нужно позвонить ToList, но зачем заставлять его оплачивать расходы, перечисляющие жадность, если возможно, он только хочет повторить один раз через перечисление? Remeber, LINQ lazy, используйте это и сделайте его работающим как можно меньше.

О том, почему я принимаю IEnumerable<T> в качестве аргумента, снова дешевое обобщение; зачем принимать только список? Почему не массив, очередь, стек, коллекция, блок итератора, hashset и т. Д.?

+0

Поскольку это ответ, не могли бы вы объяснить свой код, почему 'IEnumerable' лучше, чем' List' –

+0

@MohamedAhmed Потому что 'Where' просто возвращает' IEnumerable ', а не' List '.Кроме того: действительно ли вы хотите вернуть список, в который вы можете добавлять/удалять элементы? – HimBromBeere

+0

У меня проблема с семейством этой коллекции, я вижу, что все они похожи: \ –

 Смежные вопросы

  • Нет связанных вопросов^_^