Stateful Expression 访问者多个 运行 问题
Stateful Expression visitors multiple run issue
假设我需要编写一个表达式访问者,它也使用一些可注入服务,因此它必须有一个 public 构造函数,并且不能简单地包装在静态外观中。
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
将包含两个连接的结果。怎样才能让这样的访客完全"fool proof"?我在哪里可以重置 Result
?我可以覆盖 Visit
,但我不知道它是第一次被调用,还是在处理过程中被调用,所以我不能在那里重置它。
这样的事情可能会起作用(覆盖 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;
}
}
或者,您可以使用内部 class 将初始化与访问分开:
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;
}
}
假设我需要编写一个表达式访问者,它也使用一些可注入服务,因此它必须有一个 public 构造函数,并且不能简单地包装在静态外观中。
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
将包含两个连接的结果。怎样才能让这样的访客完全"fool proof"?我在哪里可以重置 Result
?我可以覆盖 Visit
,但我不知道它是第一次被调用,还是在处理过程中被调用,所以我不能在那里重置它。
这样的事情可能会起作用(覆盖 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;
}
}
或者,您可以使用内部 class 将初始化与访问分开:
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;
}
}