我正在尝试创建一个ExpressionVisitor,以便将表达式重新创建为输入字符串(有一些例外,捕获变量应显示为文本)。
当我需要访问表达式成员的表达式成员时,我被卡住了。我该如何做到以下几点:
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 :(得分:0)
试试这个......
ExpressionVisitor.VisitMember
答案 1 :(得分:0)
这是预期的行为,因为你将_ this.Other
与自身连接起来:
var callerPath = _path;
_path = string.Format("{0}.{1}", callerPath, _path);
你应该把它改成
_path = string.Format("{0}.{1}", _path, node.Member.Name);
即。通过将访问者应用于node.Expression
然后添加成员名称来查找前缀。