日常开发时,使用Linq和EF经常会在存在多条件查询,或者说动态条件查询时,便存在合并表达式树的情况。基于这种情况结合一些资料,写了个扩展类,代码如下:
public static class PredicateExtensions
public static Expression<Func<T, bool>> MergeAnd<T>(this Expression<Func<T, bool>> leftExpress, Expression<Func<T, bool>> rightExpress)
ParameterExpression parameter = Expression.Parameter(typeof(T), "s");
var visitor = new PredicateExpressionVisitor(parameter);
Expression left = visitor.Visit(leftExpress.Body);
Expression right = visitor.Visit(rightExpress.Body);
return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), parameter);
public static Expression<Func<T, bool>> MergeAnd<T>(this Expression<Func<T, bool>> express, params Expression<Func<T, bool>>[] arrayExpress)
if (!arrayExpress?.Any() ?? true) return express;
ParameterExpression parameter = Expression.Parameter(typeof(T), "s");
var visitor = new PredicateExpressionVisitor(parameter);
Expression<Func<T, bool>> result = null;
foreach (var curExpression in arrayExpress)
Expression left = visitor.Visit(result.Body);
Expression right = visitor.Visit(curExpression.Body);
result = Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), parameter);
return result;
public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> leftExpress, Expression<Func<T, bool>> rightExpress)
ParameterExpression parameter = Expression.Parameter(typeof(T), "s");
var visitor = new PredicateExpressionVisitor(parameter);
Expression left = visitor.Visit(leftExpress.Body);
Expression right = visitor.Visit(rightExpress.Body);
return Expression.Lambda<Func<T, bool>>(Expression.OrElse(left, right), parameter);
public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> express, params Expression<Func<T, bool>>[] arrayExpress)
if (!arrayExpress?.Any() ?? true) return express;
ParameterExpression parameter = Expression.Parameter(typeof(T), "s");
var visitor = new PredicateExpressionVisitor(parameter);
Expression<Func<T, bool>> result = null;
foreach (var curExpression in arrayExpress)
Expression left = visitor.Visit(result.Body);
Expression right = visitor.Visit(curExpression.Body);
result = Expression.Lambda<Func<T, bool>>(Expression.OrElse(left, right), parameter);
return result;
PredicateExpressionVisitor类
public class PredicateExpressionVisitor : ExpressionVisitor
public ParameterExpression _parameter { get; set; }
public PredicateExpressionVisitor(ParameterExpression parameter)
_parameter = parameter;
protected override Expression VisitParameter(ParameterExpression p)
return _parameter;
public override Expression Visit(Expression expression)
return base.Visit(expression);
class Program
static void Main(string[] args)
var models = new List<JsonData>() { new JsonData() { Id = "001", Name = "One" }, new JsonData() { Id = "002", Name = "Tow" } };
Console.WriteLine($"未处理集合:{string.Join(',', models.Select(o => o.Id))}");
Expression<Func<JsonData, bool>> expression1 = t => t.Id == "001";
Expression<Func<JsonData, bool>> expression2 = t => t.Name == "Tow";
Expression<Func<JsonData, bool>> allEexpression = expression1.MergeAnd(expression2);
Console.WriteLine(allEexpression.Body.ToString());
Console.WriteLine($"已处理集合(And):{string.Join(',', models.Where(expression1.MergeAnd(expression2).Compile()).Select(o => o.Id))}");
allEexpression = expression1.MergeOr(expression2);
Console.WriteLine(allEexpression.Body.ToString());
Console.WriteLine($"已处理集合(Or):{string.Join(',', models.Where(allEexpression.Compile()).Select(o => o.Id))}");
Console.ReadKey();
public class JsonData
public string Id { get; set; }
public string Name { get; set; }
为了代码更简洁,我们还可以在上述例子中加多两个方法,参数判断条件condition
public static class PredicateExtensions
public static Expression<Func<T, bool>> MergeAndIF<T>(this Expression<Func<T, bool>> leftExpress,
Expression<Func<T, bool>> rightExpress, bool condition)
=> condition ? leftExpress.MergeAnd(rightExpress) : leftExpress;
public static Expression<Func<T, bool>> MergeAndIF<T>(this Expression<Func<T, bool>> express, bool condition,
params Expression<Func<T, bool>>[] arrayExpress)
=> condition ? express.MergeAnd(arrayExpress) : express;
public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> leftExpress
, Expression<Func<T, bool>> rightExpress, bool condition)
=> condition ? leftExpress.MergeAnd(rightExpress) : leftExpress;
public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> express, bool condition,
params Expression<Func<T, bool>>[] arrayExpress)
=> condition ? express.MergeAnd(arrayExpress) : express;
MSDN Expression类
MSDN ExpressionVisitor类
魔王不造反
函数式编程
- 15.0w
-
Jetictors
Android
Kotlin
- 4047
-
sagacheng
Node.js
JavaScript