C#谓词列表传递给Linq Where子句

use*_*124 8 c# linq predicate where

我有一个很长的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();
Run Code Online (Sandbox Code Playgroud)

但是我收到了这个错误:

无法转换 'System.Linq.Expressions.Expression<System.Func<project.Contracts.DTOs.Note,bool>>[]' to 'System.Func<project.Contracts.DTOs.Note,bool>'

这是.where子句中的错误.拉出.where编译就好了.

xan*_*tos 6

您的代码中至少有两个错误:

List<Expression<Func<Note, bool>>> filters = new List<Expression<Func<Note, bool>>>();
Run Code Online (Sandbox Code Playgroud)

改为

List<Func<Note, bool>> filters = new List<Func<Note, bool>>();
Run Code Online (Sandbox Code Playgroud)

Expression这里不需要树木.你正在使用IEnumerable<>,而不是IQueryable<>

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

一次.Where()只接受一个谓词.你可以:

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

或其他各种解决方案,例如:

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();
Run Code Online (Sandbox Code Playgroud)

因为所有的.Where()条件都隐含在&&.


Pio*_*ski 5

我认为Hogan的很好的答案可以通过使用AnyAllLinq方法简化并缩短一点.

要获得满足所有条件的物品:

var resultAll = listOfItems.Where(p => filters.All(f => f(p)));
Run Code Online (Sandbox Code Playgroud)

并获得满足任何条件的物品:

var resultAny = listOfItems.Where(p => filters.Any(f => f(p)));
Run Code Online (Sandbox Code Playgroud)


Hog*_*gan 4

您必须循环过滤器并对每个过滤器运行测试。

您可以使用 linq 来执行此操作,如果您的任何过滤器为 true,则返回true :

.Where(p => { foreach(f in filters) if (f(p) == true) return(true); return(false)}) 
Run Code Online (Sandbox Code Playgroud)

或者像这样,如果所有过滤器都为 true,则返回true :

.Where(p => { foreach(f in filters) if (f(p) == false) return(false); return(true)}) 
Run Code Online (Sandbox Code Playgroud)