c# - Stateful Expression 访问者多次运行问题

标签 c# expression linq-expressions visitor-pattern

假设我需要编写一个表达式访问者,它也使用一些可注入(inject)服务,因此它必须有一个公共(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 将包含两个串联的结果。怎样才能让这样的访问者彻底“防傻”呢?我在哪里可以重置 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;
    }
}

或者,您可以使用内部类将初始化与访问分开:

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;
    }
}

关于c# - Stateful Expression 访问者多次运行问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34792873/

相关文章:

algorithm - 用函数解析表达式

linq - 是否有现有的表达式到 Azure 数据资源管理器 (Kusto) 查询转换器?

c# - 什么更好用: a DataGrid or ListView for displaying large amounts of data?

c# - 如何模拟网络浏览器以便网站为我提供正确的 HTML 源代码?

validation - {[A-Z] [a-z][0-9]} 文本输入的 QLineEdit 验证

R - 引用替换

c# - 使用 Expression[] 调用 (params object[])

c# - 动态添加新的 lambda 表达式以创建过滤器

c# - 如何在 C# 中捕获 SQLException?

c# - 如何在所有音频设备上播放声音