2015-04-29 2 views
7

У меня есть длинное предложение Linq Where, которое я бы хотел заполнить предикатным списком.Список предикатов C#, переданный Linq Where, раздел

List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>(); 

filters.Add(p => p.Title != null && p.Title.ToLower().Contains(searchString)); 
filters.Add(p => p.Notes != null && p.Notes.ToLower().Contains(searchString)); 
filters.Add(GlobalSearchUser((List <User> users = new List<User>() { p.user1, p.user2, p.user3, p.user4 }), searchString)); 

notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray()) 
     .Where(filters.ToArray()).Take(10).ToList(); 

Однако я получаю эту ошибку:

cannot convert from 'System.Linq.Expressions.Expression<System.Func<project.Contracts.DTOs.Note,bool>>[]' to 'System.Func<project.Contracts.DTOs.Note,bool>'

Какая ошибка на пункте .где. Вытащить компиляцию просто отлично.

ответ

3

Вам необходимо перекрыть фильтры и выполнить тест на каждом из них.

Вы можете сделать это с помощью LINQ, как это вернуть истинный если любой ваших фильтров истинны:

.Where(p => { foreach(f in filters) if (f(p) == true) return(true); return(false)}) 

или как это вернуть истинный если все ваших фильтров :

.Where(p => { foreach(f in filters) if (f(p) == false) return(false); return(true)}) 
+0

Добавить что-то о том, что он использует 'List xanatos

+0

@xanatos Да, я добавил несколько комментариев :) – Hogan

+0

Может быть лучше, если использовать '.Агрегат() 'также – moarboilerplate

0

Вы не можете просто передать массив предикатов методу where. Вам нужно либо перебрать массив, и продолжить вызов Where() для каждого выражения в массиве, либо найти способ объединить их все вместе в одно выражение и использовать это. Вы хотите использовать LinqKit, если вы идете по второму маршруту.

5

В вашем коде как минимум две ошибки:

List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>(); 

изменить его

List<Func<Note, bool>> filters = new List<Func<Note, bool>>(); 

Вам не нужно Expression деревья здесь. Вы используете IEnumerable<>, не IQueryable<>

notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray()) 
    .Where(filters.ToArray()).Take(10).ToList(); 

Там .Where() принимает один предикат в то время. Вы могли бы:

notes = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray()) 
    .Where(x => filters.All(x)).Take(10).ToList(); 

или различные другие решения, такие как:

var notesEnu = dataAccess.GetList<Note>(pn => pn.ProjectVersionID == projectVersionID, filterExtensions.ToArray()) 
       .AsEnumerable(); 

foreach (var filter in filters) 
{ 
    notesEmu = notesEmu.Where(filter); 
} 

notes = notesEnu.Take(10).ToList(); 

Поскольку все .Where() условия неявно в &&.

4

Я думаю, что отличный ответ от Хогана можно упростить и немного сократить с помощью Any и All Методы Linq.

Чтобы получить элементы, которые выполняют все условия:

var resultAll = listOfItems.Where(p => filters.All(f => f(p))); 

И чтобы получить элементы, которые выполняют какие-либо условия:

var resultAny = listOfItems.Where(p => filters.Any(f => f(p))); 
Смежные вопросы