zoukankan      html  css  js  c++  java
  • 表达式树动态拼接lambda

    动态拼接lambda表达式树

     

    前言

      最近在优化同事写的代码(我们的框架用的是dapperLambda),其中有一个这样很普通的场景——界面上提供了一些查询条件框供用户来进行过滤数据。由于dapperLambda按条件查询时是传入表达式树的参数,这样比如其中查询条件有一个是审核状态,另外五个是模糊查询,那这查询时的表达式树参数就要写两次,这样使得代码看起来有很多是重复的,而且如果查询条件多的情况下,在写那表达式树参数时也容易漏写或错写。所以我在想如果可以动态拼接这表达式树,那这代码就要精简很多了。

     正文

      也许我的上面文字描述让你不明觉里,那下面我就配以简单的代码来再说明一下这个问题:

    复制代码
    1 Expression<Func<SysUser, bool>> exp1 = s => s.UserName.Contains("1") && s.Age > 10;
    2 Expression<Func<SysUser, bool>> exp2 = s => s.UserName.Contains("1") && s.Age > 10 && s.IsEnable == 1;
    3 using (var context = new DbContext().ConnectionString(connString))
    4 {
    5     var result1 = context.Select<SysUser>(exp1).QueryMany();
    6     var result2 = context.Select<SysUser>(exp2).QueryMany();
    7 }
    复制代码

      上面代码两次查询,第一次查询结果result1的结果是用户名中包含1而且年龄大于10,而结果result2中就是在查询结果result1的条件上再加上帐号生效这一条件。所以我们看到exp1和exp2的表达式树绝大部分是相同的,在这个示例里看着这点重复代码似乎还是可以接受的,但是在真实环境下,重复的代码就不止这一点点了。因为exp2和exp1相比,exp2只是在exp1之上多加了一个条件,那我们有没有方法可以在exp1的基础上再加一个条件赋值给exp2呢?答案当然是可以的。

      表达式扩展类:

    复制代码
     1 public static class ExpressionExt
     2 {
     3     public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2)
     4     {          
     5         return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(expr1.Body, expr2.Body), expr1.Parameters);
     6     }
     7     public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,Expression<Func<T, bool>> expr2)
     8     {
     9         return Expression.Lambda<Func<T, bool>>(Expression.OrElse(expr1.Body, expr2.Body), expr1.Parameters);
    10     }
    11 }
    复制代码

      上面这代码是我们这文章的核心,我在这里顺便解释一下这个And扩展方法它是怎么做的,它这里先是使用Expression类中的静态方法AndAlso把expr1和expr2的主体拼接在一起,如果AndAlso方法返回的是BinaryExpression类型的结果,而dapperLambda的条件参数需要的是Lambda表达式树,所以这里我们需要通过Expression.Lambda方法来构造一个委托类型来创建一个Lambda表达树。

      那现在我们通过上面的扩展方法,再来优化一下我们最初举的例子看下:

    复制代码
    1 Expression<Func<SysUser, bool>> exp1 = s => s.UserName.Contains("1") && s.Age > 0;
    2 Expression<Func<SysUser, bool>> exp2 =exp1.And( s => s.IsEnable == 1);
    3 using (var context = new DbContext().ConnectionString(connString))
    4 {
    5     var result1 = context.Select<SysUser>(exp1).QueryMany();
    6     var result2 = context.Select<SysUser>(exp2).QueryMany();
    7 }
    复制代码

    结束语

     虽然这个扩展方法就只有几行代码,但是如果少了这几行代码,在我们的代码里可能就要上了几十行、几百行代码了。有时解决问题的关键就是那么一个不起眼的东西,但就是这么一个不起眼的东西就能帮我们解决一些大问题。

      说到这,让我想起了一句话——每多学一点知识,就少写一行代码。

  • 相关阅读:
    购买云主机时应该注意哪些事项
    wdcp的安装方法与常见问题
    推荐一些不错的计算机书籍(php c mysql linux等等)
    .htaccess详解及.htaccess参数说明【转】
    常用的7个.htaccess代码组织某个国家的IP访问
    最新ecshop v2.7.3版本去版权完全版
    javascript常用数组算法总结
    10道javascript笔试题
    Magento显示多货币,Magento 多货币设置
    Magento后台手动修改订单状态方法及手动修改方法php
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/5456081.html
Copyright © 2011-2022 走看看