Lambda表达式动态组装查询条件

最近比较闲,年底了,项目也进入尾声;每天就是维护一下系统,整理整理文档,整理知识点,这样才觉得有点意思;

问题

在使用Linq的where()查询的时候,不知道大家是怎么动态组装多个查询条件时,是怎么做的?我是这样做的,请看下面代码;

方法一:

1.1 Expression的扩展类

  public static class PredicateExtensions
  {
      public static Expression<Func<T, bool>> True<T>() { return f => true; }
  
      public static Expression<Func<T, bool>> False<T>() { return f => false; }
 
     public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
     {
         var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());
 
         return Expression.Lambda<Func<T, bool>>(Expression.Or(expression1.Body, invokedExpression), expression1.Parameters);
     }
 
     public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expression1, Expression<Func<T, bool>> expression2)
     {
         
         var invokedExpression = Expression.Invoke(expression2, expression1.Parameters.Cast<Expression>());//将一个委托或lambda表达式应用于参数表达式列表。

         return Expression.Lambda<Func<T, bool>>(Expression.And(expression1.Body, invokedExpression), expression1.Parameters);
     }
 }

1.2 实例化代码

            List<string> strList = new List<string>() { "郑州","上海户口", "鲁山揽锅菜", "南京酸菜鱼" };
            //传统写法
            Func<string, bool> func = (t) => t.Length > 3&&t.Contains("鱼");
            var listA=strList.Where(func).ToList();
            //使用扩展写法
            var expression=PredicateExtensions.True<string>();
            expression = expression.And(t => t.Length > 3);
            expression = expression.And(t => t.Contains("鱼"));
            var predicate = expression.Compile();
            var listB = strList.Where(predicate).ToList();

  

方法二:合并两个Expression表达式

2.1 表达式参数扩展类

    public class MyExpressionVisitor:ExpressionVisitor
    {
        private readonly ParameterExpression _parameter;

        public MyExpressionVisitor(ParameterExpression parameter)
        {
            _parameter = parameter;
        }

        public ParameterExpression Parameter
        {
            get { return _parameter; }
        }


        public Expression Nodify(Expression exp)
        {
            Expression e = this.Visit(exp);
            return e;
        }

        protected override Expression VisitParameter(ParameterExpression node)
        {
            return _parameter;
        }

    }

 2.2 实例化代码

int[] numbers = { 19, 25, 6, 8, 49, 7, 8, 0, 1, 47, 35, 30,29 };
                //表达式一
                ParameterExpression leftPara = Expression.Parameter(typeof(int), "n");
                Expression a_con = Expression.Constant(13);
                BinaryExpression a_binary = Expression.GreaterThan(leftPara, a_con);
                var a_lambda = Expression.Lambda<Func<int, bool>>(a_binary,leftPara);
                var a_result = a_lambda.Compile();
                var a_list = numbers.Where(a_result).ToList();
                //表达式二
                ParameterExpression b_leftPara = Expression.Parameter(typeof(int), "n");
                Expression b_con = Expression.Constant(30);
                BinaryExpression b_binary = Expression.LessThanOrEqual(b_leftPara, b_con);
                var b_lambda = Expression.Lambda<Func<int, bool>>(b_binary, b_leftPara);
                var b_result = b_lambda.Compile();
                var b_list = numbers.Where(b_result).ToList();


                //合并两个表达式
                var vistor = new MyExpressionVisitor(leftPara);
                Expression c_1 = vistor.Nodify(a_lambda.Body);
                Expression c_2 = vistor.Nodify(b_lambda.Body);
                BinaryExpression c_binary = Expression.AndAlso(c_1, c_2);
                var c_lambda = Expression.Lambda<Func<int, bool>>(c_binary, leftPara);
                var c_result = c_lambda.Compile();//编译表达式
                var c_list = numbers.Where(c_result).ToList(); 

方法二有点啰嗦,当时是用表达式树来创建的;大家可以用匿名表达式简单一点。但是在合并表达式的逻辑是,重新更改了一下表达式一和表达式二的参数,这样在编译的时候就可以通过了。

写的不咋样,日日精进吧。。。。

原文地址:https://www.cnblogs.com/searchbaidu/p/11937623.html