1. 程式人生 > >C#進階系列——動態Lamada(二:優化)

C#進階系列——動態Lamada(二:優化)

前言:前幾天寫了一篇動態Lamada的文章C#進階系列——動態Lamada,受園友的啟發,今天打算來重新優化下這個動態Lamada的工具類。在此做個筆記,以免以後忘了。

一、原理分析

上篇裡面我們說了動態Lamada的使用必要性以及使用場景,但是感覺用在專案裡面還不太方便,最難用的就是需要傳遞屬性名稱的字串,感覺這有點太lower了。然後就是那個列舉的使用著實感覺沒啥必要,我們只需要將Contains、Equal、LessThan、GreaterThan等方法分別封裝一個獨立的方法即可。好了,多說容易讓人頭暈,直接上程式碼吧。

二、程式碼示例

  public class LamadaExtention<Dto> where
Dto:new () { private List<Expression> m_lstExpression = null; private ParameterExpression m_Parameter = null; public LamadaExtention() { m_lstExpression = new List<Expression>(); m_Parameter = Expression.Parameter(typeof
(Dto), "x"); }
     //只讀屬性,返回生成的Lamada
public Expression<Func<Dto, bool>> Lamada {
        
get { return GetLambda(); } } /// <summary> /// 字串Contains篩選 /// </summary>
/// <param name="expProperty"></param> /// <param name="strValue"></param> public void Contains(Expression<Func<Dto, string>> expProperty, object strValue) { Expression expRes = Expression.Call(expProperty.Body, typeof(string).GetMethod("Contains"), Expression.Constant(strValue)); m_lstExpression.Add(expRes); } /// <summary> /// 等於 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void Equal(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.Equal(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 小於 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void LessThan(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.LessThan(member, Expression.Constant( strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 小於等於 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void LessThanOrEqual(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.LessThanOrEqual(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 大於 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void GreaterThan(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.GreaterThan(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); } /// <summary> /// 大於等於 /// </summary> /// <param name="expProperty"></param> /// <param name="strValue"></param> public void GreaterThanOrEqual(Expression<Func<Dto, object>> expProperty, object strValue) { var member = GetMemberExpression(expProperty); Expression expRes = Expression.GreaterThanOrEqual(member, Expression.Constant(strValue, member.Type)); m_lstExpression.Add(expRes); }private Expression<Func<Dto, bool>> GetLambda() { Expression whereExpr = null; foreach (var expr in this.m_lstExpression) { if (whereExpr == null) whereExpr = expr; else whereExpr = Expression.And(whereExpr, expr); } if (whereExpr == null) return null; return Expression.Lambda<Func<Dto, Boolean>>(whereExpr, m_Parameter); } //得到MemberExpression private MemberExpression GetMemberExpression(Expression<Func<Dto, object>> exp) { var arrSplit = exp.Body.ToString().Split("(.)".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); var strProperty = arrSplit[arrSplit.Length - 1]; MemberExpression member = Expression.PropertyOrField(m_Parameter, strProperty); return member; } }

可以看出,對於常用的操作我們封裝了Contains、Equal、LessThan、LessThanOrEqual、GreaterThan、GreaterThanOrEqual六個方法,除了Contains方法的引數直接使用了Expression<Func<DTO, string>>型別以為,其他都用的Expression<Func<DTO, object>>。因為Contains方法只可能是string型別的變數操作,而其他操作可能涉及其他型別,就是為了傳這個object型別,有個問題博主除錯了很久,由於傳過來的是object,這個要得到屬性的真是型別貌似不那麼容易了,找了很久都沒找到。最後只能通過GetMemberExpression這個方法來得到MemberExpression。

還是來看看如何使用:

     public object GetUsers(int limit, int offset, string username, string fullname)
        {
            var oLamadaExtention = new LamadaExtention<DTO_TR_SYS_USERS>();
            oLamadaExtention.Equal(x => x.USER_NAME, username);
            oLamadaExtention.LessThan(x => x.MODIFYTIME, DateTime.Now);
        var lstRes = UserManager.Find(oLamadaExtention.lamada).ToList();
     }

最大的方便就是我們想要篩選的欄位可以通過lamada點出來了,再看看之前的那種用法

oLamadaExtention.GetExpression("USER_NAME", username, ExpressionType.Contains);

有沒有瞬間高大上。USER_NAME直接點出來,比敲字串要爽吧。感謝神奇的Lamada,感謝全能的C#,感謝熱心的園友。

相關推薦

C#系列——動態Lamada優化

前言:前幾天寫了一篇動態Lamada的文章C#進階系列——動態Lamada,受園友的啟發,今天打算來重新優化下這個動態Lamada的工具類。在此做個筆記,以免以後忘了。 一、原理分析 上篇裡面我們說了動態Lamada的使用必要性以及使用場景,但是感覺用在專案裡面還不太方便,最難用的就是需要傳遞屬性名稱的字

C#系列——動態Lamada

前言:在DDD系列文章裡面,我們在後臺倉儲裡面封裝了傳遞Lamada表示式的通用方法,類似這樣:      public virtual IQueryable<TEntity> Find(Expression<Func<TEntity, bool>> express)

C#系列——WebApi 路由機制剖析你準備好了嗎?

事先 blank path can tex 全局配置 dex 找不到 save 前言:從MVC到WebApi,路由機制一直是伴隨著這些技術的一個重要組成部分。 它可以很簡單:如果你僅僅只需要會用一些簡單的路由,如/Home/Index,那麽你只需要配置一個默認路由就能簡

C#系列——WebApi 介面測試工具WebApiTestClient

前言:這兩天在整WebApi的服務,由於呼叫方是Android客戶端,Android開發人員也不懂C#語法,API裡面的介面也不能直接給他們看,沒辦法,只有整個詳細一點的文件唄。由於介面個數有點多,每個介面都要詳細說明介面作用、引數型別、返回值型別等等,寫著寫著把博主惹毛了,難道這種文件非要自己寫不成?難道網

【6】C++系列動態記憶體分配

問題:之前在寫程式的時候計劃好我們需要哪些資料,都定義好,但是有些時候我們並不知道我要處理的程式規模有多大,也不知道陣列開多大合適,是儘量大?分配了太大空間可能會造成記憶體的浪費。只有在程式真正執行起來才會知道這次執行要處理的資料規模有多大——那就有人想,能不能用變數來確定陣

C#系列——MEF實現設計上的“鬆耦合”

前言:前篇 C#進階系列——MEF實現設計上的“鬆耦合”(一) 介紹了下MEF的基礎用法,讓我們對MEF有了一個抽象的認識。當然MEF的用法可能不限於此,比如MEF的目錄服務、目錄篩選、重組部件等高階應用在這裡就不做過多講解,因為博主覺得這些用法只有在某些特定的環境下面才會用到,著實不太普遍,感覺沒有鑽下去的

C#系列——一步一步封裝自己的HtmlHelper元件BootstrapHelper

前言:上篇介紹了下封裝BootstrapHelper的一些基礎知識,這篇繼續來完善下。參考HtmlHelper的方式,這篇博主先來封裝下一些常用的表單元件。關於BootstrapHelper封裝的意義何在,上篇評論裡面已經討論得太多,這裡也不想過多糾結。總之一句話:凡事有得必有失,就看你怎麼去取捨。有興趣的可

C#系列——DDD領域驅動設計初探倉儲Repository

前言:上篇介紹了DDD設計Demo裡面的聚合劃分以及實體和聚合根的設計,這章繼續來說說DDD裡面最具爭議的話題之一的倉儲Repository,為什麼Repository會有這麼大的爭議,博主認為主要原因無非以下兩點:一是Repository的真實意圖沒有理解清楚,導致設計的紊亂,隨著專案的橫向和縱向擴充套件,

C#系列——WebApi 異常處理解決方案

機制 輸出 ges 如果 但是 rom lba slist 解決 出處:http://www.cnblogs.com/landeanfen/p/5363846.html 閱讀目錄 一、使用異常篩選器捕獲所有異常 二、HttpResponseException自

【8】C++系列過載

1、過載規則 c++幾乎可以過載全部的運算子,而且只能夠過載c++已有的運算子。 其中,不能過載的運算子:"." 、 ".*" 、"::"、"?:" 過載之後運算子的優先順序和結合性都不會改變。 運算子過載是針對新型資料的實際需要,對原有運算子進行適當的改造。例如: 使複數的物件

【7】C++系列類的繼承與派生

1、繼承的概念 繼承:在儲存原有類的屬性和功能的基礎上,擴充套件新的功能。 開發類庫的團隊和使用類庫的團隊很可能不是一個,有些東西是不能訪問的。 繼承和派生是同一個問題的不同視角: 保持已有類的特性而構建新類的過程成為繼承;在已有類的基礎上新增自己的特性而產生新類的過程叫做派生。

【5】C++系列陣列和指標2

1、實驗 實驗1:3 x 3矩陣的轉置 #include<iostream> using namespace std; void swap(int &a, int &b) { int temp = a; a = b; b = temp;

【9】C++系列泛型設計以及STL標準模板庫

1、泛型程式設計基本概念 泛型程式設計:編寫不依賴與具體資料型別的程式,將演算法從特定的資料結構中抽象出來,成為通用的。C++的模板為泛型程式設計定義了關鍵的基礎。 兩個術語:概念,模型 概念:用來界定具備一定功能的資料型別,例如:將“可以比較大小的所有資料型別(有比較

C#系列——DDD領域驅動設計初探領域服務

前言:之前一直在搭建專案架構的程式碼,有點偏離我們的主題(DDD)了,這篇我們繼續來聊聊DDD裡面另一個比較重要的知識點:領域服務。關於領域服務的使用,書中也介紹得比較晦澀,在此就根據博主自己的理解談談這個知識點的使用。 DDD領域驅動設計初探系列文章: 一、領域服務的引入 在《領域驅動設計:軟體核

C#系列——DDD領域驅動設計初探WCF搭建

前言:前面三篇分享了下DDD裡面的兩個主要特性:聚合和倉儲。領域層的搭建基本完成,當然還涉及到領域事件和領域服務的部分,後面再專案搭建的過程中慢慢引入,博主的思路是先將整個架構走通,然後一步一步來新增相關元素,使架構慢慢變得豐滿。這篇打算分享下應用層的搭建。根據DDD的設計原則,應用層不包含任何領域邏輯,它主

C#系列——一步一步封裝自己的HtmlHelper元件BootstrapHelper附原始碼

前言:之前的兩篇封裝了一些基礎的表單元件,這篇繼續來封裝幾個基於bootstrap的其他元件。和上篇不同的是,這篇的有幾個元件需要某些js檔案的支援。 BootstrapHelper系列文章目錄 一、NumberBoxExtensions NumberBoxExtensions是一個基於boot

C#系列——DDD領域驅動設計初探AutoMapper使用

前言:前篇搭建了下WCF的程式碼,就提到了DTO的概念,對於為什麼要有這麼一個DTO的物件,上章可能對於這點不太詳盡,在此不厭其煩再來提提它的作用: 從安全上面考慮,領域Model都帶有領域業務,讓Client端引用Domain Model就意味著Client端可以繞過應用層直接完成業務邏輯的呼叫,這樣

C#系列——MEF實現設計上的“鬆耦合”

前言:最近去了趟外地出差,介紹推廣小組開發的框架類產品。推廣物件是本部門在專案上面的同事——1到2年工作經驗的初級程式設計師。在給他們介紹框架時發現很多框架設計層面的知識他們都沒有接觸過,甚至沒聽說過,這下囧了~~於是乎在想該如何跟他們解釋MEF、AOP、倉儲模式等方面的東東。本來 C#基礎系列 應該還有兩篇

C#系列——DDD領域驅動設計初探倉儲Repository

前言:上篇介紹了下倉儲的程式碼架構示例以及簡單分析了倉儲了使用優勢。本章還是繼續來完善下倉儲的設計。上章說了,倉儲的最主要作用的分離領域層和具體的技術架構,使得領域層更加專注領域邏輯。那麼涉及到具體的實現的時候我們應該怎麼做呢,本章就來說說倉儲裡面具體細節方便的知識。 DDD領域驅動設計初探系列文章:

C#系列——MEF實現設計上的“鬆耦合”建構函式注入

前言:今天十一長假的第一天,本因出去走走,奈何博主最大的樂趣是假期坐在電腦前看各處堵車,順便寫寫部落格,有點收穫也是好的。關於MEF的知識,之前已經分享過三篇,為什麼有今天這篇?是因為昨天分享領域服務的時候,用到MEF的注入有參建構函式的方法,博主好奇心重,打算稍微深挖一下,這篇來對此知識點做個總結。 還是