程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> 動態表達式幫助類,動態表達式

動態表達式幫助類,動態表達式

編輯:關於.NET

動態表達式幫助類,動態表達式


以前有一段時間被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         }

 

這樣就簡單干淨多了,爽

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved