动态表达式帮助类

以前有一段时间被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         }

 

这样就简单干净多了,爽

 

posted on 2016-12-05 14:19  Jade_K  阅读(980)  评论(0编辑  收藏  举报

导航