1. 程式人生 > >獲取Lambda表示式內表示式的值

獲取Lambda表示式內表示式的值

  隨著Linq的盛行,對於Linq和Lmabda表示式的使用也越來越多,Lambda表示式在.net framework 3.5中提出來,Lambda表示式是一個匿名方法,通常在LINQ中被用來建立委託,但是當我們利用Lmabda表示式來實現某些操作的時候,分解內部的表示式樹結構就很重要了,例如我們要在一些方法呼叫當中直接使用 t => t.Name 的方式將屬性Name獲取出來,這樣我們就不用自己去寫字串,且在屬性發生改變的時候編譯器可以幫助我們進行重構和檢測。

  當我們要實現以上方式的時候,就不再只是匿名委託了,而是要使用到Expression,它位於System.Linq.Expressions名稱空間內,具體的資料大家可以到MSDN內找到,這裡就不具體列出來了。在表示式內{ 類.屬性 }的格式是一個MemberExpression物件,節點型別是MemberAccess,由於我們要獲取的屬性對應的型別不一定都一樣,因此獲取屬性名的委託就只能定義為Func<T, object>了,大致程式碼如下:

publicstaticstringResloveName<T>(Expression<Func<T,object>> expression){var exp = expression.BodyasMemberExpression;string expStr = exp.ToString();return expStr.Substring(expStr.IndexOf(".")+1);}

   現在有如下程式碼:

User user =newUser{Name="Xiao Ming"};Expression<Func<User,bool>>
exp = u => u.Name== user.Name;

  假如要利用這個二元表示式來構建SQL的話,應該如何去分解這個表示式呢,我的做法是首先將表示式的主體轉化為BinaryExpression,然後分別去判斷Left、Right屬性內的表示式(Left、Right屬性表示式都是MemberExpression)的Expression是否跟exp的引數表示式相同,將不同的表示式的值計算出來,用於當作引數,大致程式碼如下:

BinaryExpression binaryExp = exp.BodyasBinaryExpression;Expression constantExp 
=(binaryExp.LeftasMemberExpression).Expression== exp.Parameters[0]? binaryExp.Right: binaryExp.Left;string value =Expression.Lambda(constantExp).Compile().DynamicInvoke().ToString();

  從繼承體系上看,可以發現所有泛型表示式都是繼承自LambdaExpression的,因此可以過載一個方法,大致程式碼如下:

publicstaticstringResloveName(Expression<Func<T,object>> expression){returnResloveName(expression asLambdaExpression);}publicstaticstringResloveName(LambdaExpression expression){var exp = expression.BodyasMemberExpression;string expStr = exp.ToString();return expStr.Substring(expStr.IndexOf(".")+1);}

   希望以上的程式碼能幫助大家在表示式的應用方面有所幫助,謝謝!