質問

私は現在、2つのアセンブリを持って、ビジターパターンについて質問があります。私の最初のアセンブリは、いくつかのインタフェースが含まれています。

public interface INode
{
    void Visit(INodeVisitor visitor);
}

public interface INodeVisitor
{
    void VisitContainer(IContainer container);
}

public interface IContainer : INode
{
}

そして、私の第2組立

    class Program
{
    static void Main(string[] args)
    {
        ContainerVisitor visitor = new ContainerVisitor();
        visitor.VisitContainer(new Container());
    }
}

public class ContainerVisitor : INodeVisitor
{
    public void VisitContainer(IContainer value)
    {
        Container container = value as Container;
        // Do some stuff...
    }
}

public class Container : IContainer
{        
    public void Visit(INodeVisitor visitor)
    {
        visitor.VisitContainer(this);
    }
}

私は何をしたいことはContainerVisitorクラスにキャストする必要性を避けるためですが、私は直接コンテナを参照したいです。私はコンテナを使用するインターフェイスのINodeVisitorインタフェースを変更することはできません。何か案は?私はちょうどキャストべきでしょうか?

乾杯

ロアン

役に立ちましたか?

解決

キャストは避けられないですが、実際のContainerVisitorクラスからそれを除去するためのビットを出して抽象でします。

public class NodeVisitor<T> : INodeVisitor where T : IContainer {
  public void VisitContainer(T node) {
    var container = node as T;
    if ( container != null ) { 
      VisitTyped(container);
    }
  }
  protected abstract VisitContainerTyped(T container);
}

今ContainerVisitorがNodeVisitorから派生し、キャストを回避することができます。

public class ContainerVisitor : NodeVisitor<Container>{
    protected override void VisitContainerTyped(Container container){
        // Do some stuff...
    }
}

他のヒント

私はそれがの有効なのそれはContainerインスタンスであると仮定することはないと思います。私は、完全に有効に、私自身のIContainerの実装を書くことができ、そして、あなたの実装では、インターフェイスベースの抽象化の全体のポイントを壊し、それにチョークでしょう。私はクラスではなくインタフェースを使用することができので、あなたはまた、(有効に)ただ、(Containerをサポートするために、明示的な実装を使用して)IContainerを受け入れるようにAPIを変更することはできません。

INodeVisitor visitor = new ContainerVisitor();
visitor.VisitContainer(myBespokeContainer);

あなたは基本クラスから何かをオプションでサポートが必要な場合は、その後、あなたはそれを検出するため「として、」使用する必要があるとしています。他に何か、あなたは抽象化を壊している。

あなたはもっと自分のいるIContainerインターフェイスを定義することができない限り、あなたはキャストを避けることができなくなります。マークが言うように、それはインターフェイスベースの抽象化の目的に反します。

public interface IContainer : INode
{
    void Add(IComponent component);
    void Add(IComponent component, string name);
    void Remove(IComponent component);
    ComponentCollection Components { get; }
}

より明確いるIContainerを使用すると、あなたの訪問者は、任意の鋳造を行う必要がありません。

public class ContainerVisitor : INodeVisitor
{
    public void VisitContainer(IContainer container)
    {
        foreach (IComponent component in container.Components)
        {
            // ...
        }
    }
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top