獲取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>了,大致代碼如下:

public static string ResloveName<T>(Expression<Func<T, object>> expression)
{
    var exp = expression.Body as MemberExpression;
    string expStr = exp.ToString();
    return expStr.Substring(expStr.IndexOf(".") + 1);
}

   現在有如下代碼:

User user = new User { 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.Body as BinaryExpression;
Expression constantExp = (binaryExp.Left as MemberExpression).Expression == exp.Parameters[0] ? binaryExp.Right : binaryExp.Left;
string value = Expression.Lambda(constantExp).Compile().DynamicInvoke().ToString();

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

public static string ResloveName(Expression<Func<T, object>> expression)
{
    return ResloveName(expression as LambdaExpression);
}

public static string ResloveName(LambdaExpression expression)
{
    var exp = expression.Body as MemberExpression;
    string expStr = exp.ToString();
    return expStr.Substring(expStr.IndexOf(".") + 1);
}

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM