2012-06-08 202 views
1

與問題How can I get property name strings used in a Func of T類似。獲取拉姆達表達式屬性的字符串版本

比方說,我有存儲這樣的變量lambda表達式 稱爲「吸氣劑」

Expression<Func<Customer, string>> productNameSelector = 
    customer => customer.Product.Name; 

我怎麼能提取字符串「Product.Name」?

我現在

var expression = productNameSelector.ToString(); 
var token = expression.Substring(expression.IndexOf('.') + 1); 

固定它有點haxy但我想找到一個更堅實的方式;-)

回答

2

你表達的表達式樹看起來是這樣的:

  . 
     /\ 
     . Name 
     /\ 
customer Product 

如您所見,沒有代表Product.Name的節點。但是你可以使用遞歸和建立自己的字符串:

public static string GetPropertyPath(LambdaExpression expression) 
{ 
    return GetPropertyPathInternal(expression.Body); 
} 

private static string GetPropertyPathInternal(Expression expression) 
{ 
    // the node represents parameter of the expression; we're ignoring it 
    if (expression.NodeType == ExpressionType.Parameter) 
     return null; 

    // the node is a member access; use recursion to get the left part 
    // and then append the right part to it 
    if (expression.NodeType == ExpressionType.MemberAccess) 
    { 
     var memberExpression = (MemberExpression)expression; 

     string left = GetPropertyPathInternal(memberExpression.Expression); 
     string right = memberExpression.Member.Name; 

     if (left == null) 
      return right; 

     return string.Format("{0}.{1}", left, right); 
    } 

    throw new InvalidOperationException(
     string.Format("Unknown expression type {0}.", expression.NodeType)); 
} 
+0

這就是我期待的那種解決方案!在我的項目中對此進行了測試,它的功能如同一種魅力! –

1

如果你有,你可以使用ToString方法來提取表達式字符串表示:

Expression<Func<Customer, string>> productNameSelector = 
    customer => customer.Product.Name; 

var expression = productNameSelector.ToString(); 
var token = expression.Substring(expression.IndexOf('.') + 1); 
+0

好你基本上是什麼,我寫了一個更具可讀性和更清潔的版本(+1),但它仍然看起來像一個蹩腳的解決方法,或者我應該相信這個在生產中工作...... :) –

+0

這是哪種方法的問題?你不喜歡它? –

+0

@MatteoMigliore我認爲它總是能正常工作還不太清楚。如果你給它「怪異」的表達,它可能會產生意想不到的結果,而不是失敗的例外。當它發生異常時失敗,它的消息對你無能爲力。 – svick