将谓词组合成表达式

时间:2015-11-01 18:13:18

标签: c# linq

我的目标是使用此签名:

IEnumerable<T> SearchFor(Expression<Func<T, bool>> expression);

并且想要AND这两个谓词:

Func<Employee, bool> isActiveEmployee = e => e.DateFired == null;
Func<Employee, bool> isNewEmployee = e => e.DateHired >= DateTime.Today.AddDays(-90);

成一个表达式。我怎么能实现这个目标呢?

PS:

基本上,我正在尝试使用this。但是这句话:

var body = (BinaryExpression) expression.Body;
取自here的方法GetDynamicQuery中的

引发异常:

  

无法转换类型为#System; Linq.Expressions.InstanceMethodCallExpressionN&#39;的对象输入&#39; System.Linq.Expressions.BinaryExpression&#39;。

使用这种方法:

Expression<Func<Employee, bool>> isActiveEmployee = e => e.DateFired == null;
Expression<Func<Employee, bool>> isNewEmployee = e => e.DateHired >= DateTime.Today.AddDays(-90);

Expression<Func<Employee, bool>> combined_expression = e => isActiveEmployee.Invoke(e) && isNewEmployee.Invoke(e);

1 个答案:

答案 0 :(得分:1)

我假设您需要一个可以通过许多数据访问框架转换为SQL的真实表达式。

一种解决方案是使用LinqKit,如下所示:

Expression<Func<Employee, bool>> isActiveEmployee = e => e.DateFired == null;
Expression<Func<Employee, bool>> isNewEmployee = e => e.DateHired >= DateTime.Today.AddDays(-90);

Expression<Func<Employee, bool>> combined_expression = e => isActiveEmployee.Invoke(e) && isNewEmployee.Invoke(e);

然后你可以使用LinqKit中的IQueryable方法包裹你的AsExpandable,如下所示:

var query = context.Employees.AsExpandable().Where(combined_expression);

或者,如果您不想调用AsExpandable,则可以展开新表达式,然后像使用其他表达式一样使用它:

Expression<Func<Employee, bool>> combined_expression = e => isActiveEmployee.Invoke(e) && isNewEmployee.Invoke(e);

combined_expression = combined_expression.Expand();

var query = context.Employees.Where(combined_expression);

<强>更新

对于您提供的第二个示例,您可以执行以下操作:

Expression<Func<Employee, bool>> expression1 = e => e.Guid == new Guid("28D3BCFB-9472-4141-BD88-BE5E7E1230F0");

Expression<Func<Employee, bool>> expression2 = e => e.Guid == new Guid("0F0DBA45-F842-4E46-9ED4-F50B5BCF0509");

Expression<Func<Employee, bool>> combined_expression = e => expression1.Invoke(e) || expression2.Invoke(e);

combined_expression = combined_expression.Expand();

// use combined_expression