前言
日常开发时,使用Linq和EF经常会在存在多条件查询,或者说动态条件查询时,便存在合并表达式树的情况。基于这种情况结合一些资料,写了个扩展类,代码如下:
代码实现
- /// <summary>
- /// Linq表达式扩展方法
- /// </summary>
- public static class PredicateExtensions
- {
- /// <summary>
- /// 以And合并单个表达式
- /// 此处采用AndAlso实现“最短路径”,避免掉额外且不需要的比较运算式
- /// </summary>
- public static Expression<Func<T, bool>> MergeAnd<T>(this Expression<Func<T, bool>> leftExpress, Expression<Func<T, bool>> rightExpress)
- {
- //声明传递参数(也就是表达式树里面的参数别名s)
- 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);
- }
- /// <summary>
- /// 以And合并多个表达式
- /// 此处采用AndAlso实现“最短路径”,避免掉额外且不需要的比较运算式
- /// </summary>
- 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;
- //声明传递参数(也就是表达式树里面的参数别名s)
- 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;
- }
- /// <summary>
- /// 以Or合并表达式
- /// 此处采用OrElse实现“最短路径”,避免掉额外且不需要的比较运算式
- /// </summary>
- public static Expression<Func<T, bool>> MergeOr<T>(this Expression<Func<T, bool>> leftExpress, Expression<Func<T, bool>> rightExpress)
- {
- //声明传递参数(也就是表达式树里面的参数别名s)
- 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);
- }
- /// <summary>
- /// 以Or合并多个表达式
- /// 此处采用AndAlso实现“最短路径”,避免掉额外且不需要的比较运算式
- /// </summary>
- 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;
- //声明传递参数(也就是表达式树里面的参数别名s)
- 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;
- }
- }
复制代码 使用例子
- 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))}");
- //表达式1
- Expression<Func<JsonData, bool>> expression1 = t => t.Id == "001";
- //表达式2
- Expression<Func<JsonData, bool>> expression2 = t => t.Name == "Tow";
- //合并成 t => t.Id=="001" && t.Name=="One"
- 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))}");
- //合并成 t => t.Id=="001" || t.Name=="One"
- 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; }
- }
复制代码 结果

相关资料
MSDN Expression类
MSDN ExpressionVisitor类
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |