C# 访问者模式和逻辑操作

C# 访问者模式和逻辑操作,c#,design-patterns,visitor,C#,Design Patterns,Visitor,好吧,我一直在努力解决这个问题 我已经创建了一个带有逻辑节点的树结构,例如And,Or,Equals,Between。 我不希望这些节点除了访问者的accept方法之外还有什么,因为将有更多具有不同实现的访问者 例如,我正在参观和。它首先访问自身,所以我知道我正在处理一个and,然后它访问左侧和右侧节点。可以是前面提到的任何节点 问题是,我需要一种方法来检查我是否完成了对子节点的访问。 例如,我想要这个输出 “和(Equals()/或(Equals()/Between())” 但因为我不知道孩子

好吧,我一直在努力解决这个问题

我已经创建了一个带有逻辑节点的树结构,例如And,Or,Equals,Between。 我不希望这些节点除了访问者的accept方法之外还有什么,因为将有更多具有不同实现的访问者

例如,我正在参观和。它首先访问自身,所以我知道我正在处理一个and,然后它访问左侧和右侧节点。可以是前面提到的任何节点

问题是,我需要一种方法来检查我是否完成了对子节点的访问。 例如,我想要这个输出

“和(Equals()/或(Equals()/Between())”

但因为我不知道孩子们什么时候被看望过,所以事情会是这样的

“And()等于()/或()等于()/介于()


关于如何克服这个问题有什么建议吗?

因此,当访问节点时,您需要跟踪您在树中的位置。要做到这一点,您需要引入某种上下文

大概是这样的:

public class VisitContext
{
    // Visited node
    public VisitedType Visited { get; set; }

    // Visited node is the left child node
    public bool IsLeftNode { get; set; }

   // Visited node is the right child node
    public bool IsRightNode { get; set; }
}
public string Visit(Or element)
{
   return "Or(" + element.Left.Accept(this) + "," + element.Right.Accept(this) + ")";
}
所以访客得到了这份合同:

public interface IVisitor
{
    public void Visit(VisitContext context);
}
现在你只需要遍历它。关键是要有一个受保护的重载,告诉孩子们他们是哪种类型。注意递归调用

public class VisitedType
{
    public void Accept(IVisitor visitor)
    {
        var context = new VisitContext{ Visited = this };
        visitor.Visit(context);

        _leftNode.AcceptAsLeft(context);
        _rightNode.AcceptAsRight(context);
    }

    protected void AcceptAsLeft(VisitContext context)
    {
        context.IsLeftNode=true;
        context.IsRightNode=false;
        visitor.Visit(context);

        _leftNode.AcceptAsLeft(context);
        _rightNode.AcceptAsRight(context);
    }

    protected void AcceptAsRight(VisitContext context)
    {
        context.IsLeftNode=false;
        context.IsRightNode=true;
        visitor.Visit(context);

        _leftNode.AcceptAsLeft(context);
        _rightNode.AcceptAsRight(context);
    }
}
现在你知道什么时候你在树上左右移动了,但是你仍然不知道你在树上的位置。为此,让我们引入一个沿袭/面包屑来跟踪我们当前的路径

public class VisitContext
{
    public VisitedType Visited { get; set; }
    public bool IsLeftNode { get; set; }
    public bool IsRightNode { get; set; }

    // this.
    public LinkedList<VisitedType> Lineage { get; set; }       
}
公共类访问上下文
{
公共访问类型已访问{get;set;}
公共bool IsLeftNode{get;set;}
公共bool IsRightNode{get;set;}
//这个。
公共链接列表沿袭{get;set;}
}
并更新访问类型:

public class VisitedType
{
    public void Accept(IVisitor visitor)
    {
        var context = new VisitContext{ Visited = this, Lineage = new LinkedList<VisitedType>() };
        context.Lineage.AddLast(this);
        visitor.Visit(context);

        _leftNode.AcceptAsLeft(context);
        _rightNode.AcceptAsRight(context);
    }

    protected void AcceptAsLeft(VisitContext context)
    {
        //add a bread crumb
        context.Lineage.AddLast(this);
        context.IsLeftNode=true;
        context.IsRightNode=false;
        visitor.Visit(context);

        _leftNode.AcceptAsLeft(context);
        _rightNode.AcceptAsRight(context);

        //remove us when we've visited our children
        context.Lineage.RemoveLast();
    }

    protected void AcceptAsRight(VisitContext context)
    {
        //add a bread crumb
        context.Lineage.AddLast(this);
        context.IsLeftNode=false;
        context.IsRightNode=true;
        visitor.Visit(context);

        _leftNode.AcceptAsLeft(context);
        _rightNode.AcceptAsRight(context);

        //remove us when we've visited our children
        context.Lineage.RemoveLast();
    }
}
公共类VisitedType
{
公共无效接受(IVisitor访客)
{
var context=new VisitContext{Visited=this,relegate=new LinkedList()};
context.relege.AddLast(this);
访问者访问(上下文);
_leftNode.AcceptsLeft(上下文);
_rightNode.AcceptsRight(上下文);
}
受保护的void acceptsLeft(VisitContext上下文)
{
//加面包屑
context.relege.AddLast(this);
context.IsLeftNode=true;
context.IsRightNode=false;
访问者访问(上下文);
_leftNode.AcceptsLeft(上下文);
_rightNode.AcceptsRight(上下文);
//当我们探望孩子时,把我们带走
context.relegate.RemoveLast();
}
受保护的无效接受权限(VisitContext上下文)
{
//加面包屑
context.relege.AddLast(this);
context.IsLeftNode=false;
context.IsRightNode=true;
访问者访问(上下文);
_leftNode.AcceptsLeft(上下文);
_rightNode.AcceptsRight(上下文);
//当我们探望孩子时,把我们带走
context.relegate.RemoveLast();
}
}

现在,您应该能够通过层次结构跟踪访问。这要归功于递归调用,在通过层次结构时,递归调用将继续构建面包屑。

感谢jgauffin提供的提示! 但是我得到了一些小的东西,按照我想要的方式工作

开始使用泛型

public abstract class Node
{
    public abstract T Accept<T>(IVisitor<T> visitor);
}

public interface IVisitor<T>
{
    T Visit(And element);
    T Visit(Or element);
    T Visit(Equals element);
}

因此,我的程序只接受根节点,并将打印出我前面提到的字符串。

检查您访问子节点是否已完成?您的意思是什么?在
.accept()结尾处是否已完成
call?是否异步执行?欢迎使用Stack Overflow。如果您喜欢@jgauffin的答案,您应该投票支持并/或接受它。