zoukankan      html  css  js  c++  java
  • 动态表达式帮助类

    以前有一段时间被EF LINQ中的动态表达式实现困扰,因为在实际项目中有很多的可变条件搜索,比方说,我要查询一个人,那么搜索条件就可能有按照用户名搜索、按照昵称搜索、按照年龄搜索,那么这些条件组合在一起就会有很多种,但是我们不肯能为每一种单独写一段程序,所以应该把这些可能产生条件抽离出来。

    网上找了很多,都不是很理想,不知道哪里找到的代码(具体哪里忘了,也就懒得再找一次了),贴在这,希望对其他人也有帮助

    具体代码:

     1 /* ===============================================================
     2  * 创 建 者:wms
     3  * 创建日期:2016/12/5 13:11:22
     4  * 功能描述:动态表达式帮助类
     5  * ===============================================================*/
     6 
     7 using System;
     8 using System.Linq;
     9 using System.Linq.Expressions;
    10 
    11 namespace Framework.Core.Linq
    12 {
    13     /// <summary>
    14     /// 动态表达式帮助类
    15     /// </summary>
    16     public static class ExpressionHelper
    17     {
    18         /// <summary>
    19         /// Creates a predicate that evaluates to true.
    20         /// </summary>
    21         public static Expression<Func<T, bool>> True<T>() { return param => true; }
    22 
    23         /// <summary>
    24         /// Creates a predicate that evaluates to false.
    25         /// </summary>
    26         public static Expression<Func<T, bool>> False<T>() { return param => false; }
    27 
    28         /// <summary>
    29         /// Creates a predicate expression from the specified lambda expression.
    30         /// </summary>
    31         public static Expression<Func<T, bool>> Create<T>(Expression<Func<T, bool>> predicate) { return predicate; }
    32 
    33         /// <summary>
    34         /// Combines the first predicate with the second using the logical "and".
    35         /// </summary>
    36         public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
    37         {
    38             return first.Compose(second, Expression.AndAlso);
    39         }
    40 
    41         /// <summary>
    42         /// Combines the first predicate with the second using the logical "or".
    43         /// </summary>
    44         public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> first, Expression<Func<T, bool>> second)
    45         {
    46             return first.Compose(second, Expression.OrElse);
    47         }
    48 
    49         /// <summary>
    50         /// Negates the predicate.
    51         /// </summary>
    52         public static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expression)
    53         {
    54             var negated = Expression.Not(expression.Body);
    55             return Expression.Lambda<Func<T, bool>>(negated, expression.Parameters);
    56         }
    57 
    58         /// <summary>
    59         /// Combines the first expression with the second using the specified merge function.
    60         /// </summary>
    61         static Expression<T> Compose<T>(this Expression<T> first, Expression<T> second, Func<Expression, Expression, Expression> merge)
    62         {
    63             // zip parameters (map from parameters of second to parameters of first)
    64             var map = first.Parameters
    65                 .Select((f, i) => new { f, s = second.Parameters[i] })
    66                 .ToDictionary(p => p.s, p => p.f);
    67 
    68             // replace parameters in the second lambda expression with the parameters in the first
    69             var secondBody = ParameterRebinder.ReplaceParameters(map, second.Body);
    70 
    71             // create a merged lambda expression with parameters from the first expression
    72             return Expression.Lambda<T>(merge(first.Body, secondBody), first.Parameters);
    73         }
    74     }
    75 }
     1 using System.Collections.Generic;
     2 using System.Linq.Expressions;
     3 
     4 namespace Framework.Core.Linq
     5 {
     6     /// <summary>
     7     /// ParameterRebinder
     8     /// </summary>
     9     public class ParameterRebinder : ExpressionVisitor
    10     {
    11         /// <summary>
    12         /// The ParameterExpression map
    13         /// </summary>
    14         readonly Dictionary<ParameterExpression, ParameterExpression> map;
    15 
    16         /// <summary>
    17         /// Initializes a new instance of the <see cref="ParameterRebinder"/> class.
    18         /// </summary>
    19         /// <param name="map">The map.</param>
    20         ParameterRebinder(Dictionary<ParameterExpression, ParameterExpression> map)
    21         {
    22             this.map = map ?? new Dictionary<ParameterExpression, ParameterExpression>();
    23         }
    24 
    25         /// <summary>
    26         /// Replaces the parameters.
    27         /// </summary>
    28         /// <param name="map">The map.</param>
    29         /// <param name="exp">The exp.</param>
    30         /// <returns>Expression</returns>
    31         public static Expression ReplaceParameters(Dictionary<ParameterExpression, ParameterExpression> map, Expression exp)
    32         {
    33             return new ParameterRebinder(map).Visit(exp);
    34         }
    35 
    36         /// <summary>
    37         /// Visits the parameter.
    38         /// </summary>
    39         /// <param name="p">The p.</param>
    40         /// <returns>Expression</returns>
    41         protected override Expression VisitParameter(ParameterExpression p)
    42         {
    43             ParameterExpression replacement;
    44 
    45             if (map.TryGetValue(p, out replacement))
    46             {
    47                 p = replacement;
    48             }
    49 
    50             return base.VisitParameter(p);
    51         }
    52     }
    53 }

    我们看一下具体使用方法

     假如要查询用户信息,查询条件有用户名、年龄、昵称

    Action代码:

     1         public ActionResult Index(TestUser user)
     2         {
     3             Expression<Func<TestUser, bool>> predicate = Framework.Core.Linq.ExpressionHelper.True<TestUser>();
     4             if (!string.IsNullOrEmpty(user.UserName))
     5             {
     6                 predicate = predicate.And(m => m.UserName.Contains(user.UserName));
     7             }
     8             if (user.Age != null)
     9             {
    10                 predicate = predicate.And(m => m.Age == user.Age);
    11             }
    12             if (!string.IsNullOrEmpty(user.NickName))
    13             {
    14                 predicate = predicate.And(m => m.NickName.Contains(user.NickName));
    15             }
    16             TestContext dbContext = new TestContext();
    17 
    18             var list = dbContext.TestUser.Where(predicate).ToList();
    19 
    20             return View(list);
    21         }

    这样就简单干净多了,爽

    作者:王家大人
    出处:http://wms01.cnblogs.com
    限于本人水平,如果文章和代码有表述不当之处,还请不吝赐教。
    声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    node nmp 的关键信息
    PHP中定义常量的区别,define() 与 const
    mac电脑如何快速显示桌面及切换应用
    Mac拷贝/复制文件夹路径快捷键
    比 file_get_contents() 更优的 cURL 详解(附实例)
    PHP fopen/file_get_contents与curl性能比较
    在phpstorm中如何对比文件呢?
    PHP 基础篇
    MySQL 中视图和表的区别以及联系是什么?
    MAC将根目录文件夹的权限赋给用户
  • 原文地址:https://www.cnblogs.com/wms01/p/6133772.html
Copyright © 2011-2022 走看看