2013-07-11 45 views
0

我想創建一個ExpressionVisitor以重新創建表達式作爲輸入字符串(有一些例外,如捕獲變量應顯示爲文本)。自定義ExpressionTree ToString

當我需要訪問表達式成員的表達式成員時,我被卡住了。我怎樣才能讓下面的:

public class Starter 
{ 
    private static void Main(string[] args) 
    { 
     var test = new SomeClass(); 
     test.EchoTest(); 
     Console.ReadLine(); 
    } 
} 

public class SomeClass 
{ 
    public string StringMember { get; set; } 
    public SomeClass Other { get; set; } 

    public void EchoTest() 
    { 
     var capturedString = "localStringValue"; 

     Echo((() => "hardcodedString"));//Ok :() => "hardcodedString" 
     Echo((() => capturedString));//Ok :() => "localStringValue" (I want the value in this case) 
     Echo((() => this.StringMember));//Ok :() => this.StringMember 
     Echo((() => this.Other.StringMember));//Failed, expected :() => this.Other.StringMember , received :() => this.Other.this.Other 
    } 

    private void Echo(Expression<Func<string>> expression) 
    { 
     Console.WriteLine(PathVisitor.GetPath(expression)); 
    } 
} 

public class PathVisitor : ExpressionVisitor 
{ 
    private string _path; 

    protected override Expression VisitLambda<T>(Expression<T> node) 
    { 
     Visit(node.Body); 
     _path = string.Format("() => {0}", _path); 
     return node; 
    } 

    protected override Expression VisitConstant(ConstantExpression node) 
    { 
     _path = string.Format("\"{0}\"", node.Value); 
     return node; 
    } 

    protected override Expression VisitMember(MemberExpression node) 
    { 
     var generatedClass = null != Attribute.GetCustomAttribute(node.Expression.Type, typeof(CompilerGeneratedAttribute)); 
     if (node.Expression.NodeType == ExpressionType.Constant && generatedClass) 
     { 
      var getter = Expression.Lambda(node); //let's eval captured Variable 
      _path = string.Format("\"{0}\"", getter.Compile().DynamicInvoke()); 
     } 
     else if (node.Expression.NodeType == ExpressionType.Constant) 
     { 
      _path = string.Format("this.{0}", node.Member.Name); 
     } 
     else 
     { 
      base.Visit(node.Expression); 
      var callerPath = _path; 
      _path = string.Format("{0}.{1}", callerPath, _path); 
     } 

     return node; 
    } 

    public static string GetPath(Expression expression) 
    { 
     var visitor = new PathVisitor(); 
     visitor.Visit(expression); 
     return visitor._path; 
    } 
} 

回答

0

嘗試......

ExpressionVisitor.VisitMember 
0

這因爲您連接_path至極是this.Other與自身預期behviour:

 

var callerPath = _path; 
_path = string.Format("{0}.{1}", callerPath, _path); 
 

你應該改變它到

 

_path = string.Format("{0}.{1}", _path, node.Member.Name); 
 

即通過將您的訪問者應用到node.Expression然後添加成員名稱來查找前綴。

相關問題