zoukankan      html  css  js  c++  java
  • 动态拼接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 }

    结束语

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

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

  • 相关阅读:
    LeetCode 453 Minimum Moves to Equal Array Elements
    LeetCode 112 Path Sum
    LeetCode 437 Path Sum III
    LeetCode 263 Ugly Number
    Solutions and Summay for Linked List Naive and Easy Questions
    AWS–Sysops notes
    Linked List
    All About Linked List
    datatable fix error–Invalid JSON response
    [转]反编译c#的相关问题
  • 原文地址:https://www.cnblogs.com/Lau7/p/5451985.html
Copyright © 2011-2022 走看看