標籤:
前言
最近在最佳化同事寫的代碼(我們的架構用的是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 }結束語
雖然這個擴充方法就只有幾行代碼,但是如果少了這幾行代碼,在我們的代碼裡可能就要上了幾十行、幾百行代碼了。有時解決問題的關鍵就是那麼一個不起眼的東西,但就是這麼一個不起眼的東西就能幫我們解決一些大問題。
說到這,讓我想起了一句話——每多學一點知識,就少寫一行代碼。
運算式樹狀架構動態拼接lambda