让我们说我需要编写一个表达式访问者,它也使用一些可注入服务,因此它必须有一个公共构造函数,并且不能简单地包装在静态外观中。
public class ProcessingVisitor : ExpressionVisitor {
IProcessor _processor;
public string Result { get; private set; }
public ProcessingVisitor(IProcessor processor) {
_processor = processor;
}
protected override Expression VisitBinary(BinaryExpression node)
{
// visit left and right
// ... and do something with _processor
Result += // ... append something to result
return node;
}
}
现在,当我想使用这个访问者时,我会实例化它并像这样使用它
var myExpression = ...;
var myVisitor = new ProcessingVisitor();
myVisitor.Visit(myExpression);
var result = myVisitor.Result;
现在想象一下 - 例如偶然 - 在另一个表达式上运行Visit
。然后Result
将包含两个连接的结果。我怎样才能完全成为这样一个访客"傻瓜证明"?我在哪里可以重置Result
?我可以覆盖Visit
,但我不知道内部是否第一次调用,或者在处理过程中调用它,所以我无法重置它在那里。
答案 0 :(得分:1)
这样的事情可能会起作用(覆盖Visit
来跟踪你的根节点是什么):
public class ProcessingVisitor : ExpressionVisitor
{
IProcessor _processor;
private Expression _rootExpression = null;
public string Result { get; private set; }
public ProcessingVisitor(IProcessor processor)
{
_processor = processor;
}
protected override Expression VisitBinary(BinaryExpression node)
{
// visit left and right
// ... and do something with _processor
Result += "";// ... append something to result
return node;
}
public override Expression Visit(Expression node)
{
if (_rootExpression == null)
{
_rootExpression = node;
Result = null;
}
var toReturn = base.Visit(node);
if (_rootExpression == node)
_rootExpression = null;
return toReturn;
}
}
或者,您可以使用内部课程将初始化与访问分开:
public class ProcessingVisitor : ExpressionVisitor
{
IProcessor _processor;
#region Inner Class
internal class _Implementation : ExpressionVisitor
{
IProcessor _processor;
internal string Result { get; set; }
internal _Implementation(IProcessor processor)
{
_processor = processor;
}
protected override Expression VisitBinary(BinaryExpression node)
{
// visit left and right
// ... and do something with _processor
Result += "";// ... append something to result
return node;
}
internal Expression VisitFresh(Expression node)
{
Result = null;
return base.Visit(node);
}
}
#endregion
public string Result { get; private set; }
public ProcessingVisitor(IProcessor processor)
{
_processor = processor;
}
public override Expression Visit(Expression node)
{
var impl = new _Implementation(_processor);
var toReturn = impl.VisitFresh(node);
Result = impl.Result;
return toReturn;
}
}