2012-06-08 173 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