• 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(); 

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

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

  • 相关阅读:
    bzoj1660[Usaco2006 Nov]Bad Hair Day 乱发节*
    bzoj1624[Usaco2008 Open] Clear And Present Danger 寻宝之路*
    bzoj1617[Usaco2008 Mar]River Crossing渡河问题*
    bzoj1681[Usaco2005 Mar]Checking an Alibi 不在场的证明*
    bzoj1631[Usaco2007 Feb]Cow Party*
    bzoj1854[Scoi2010]游戏
    bzoj2338[HNOI2011]数矩形
    bzoj1096[ZJOI2007]仓库建设
    继承原理、派生重用
    面向对象三大特性——继承(含派生)
  • 原文地址:https://www.cnblogs.com/searchbaidu/p/11937623.html
Copyright © 2020-2023  润新知