3

訪問者パターンについて質問があります。現在、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 クラスでキャストする必要を避けることです。Container を直接参照したいと思います。インターフェイス INodeVisitor インターフェイスを Container を使用するように変更できません。何か案は?キャストするだけでいいですか?

乾杯

ローハン

4

3 に答える 3

3

キャストは避けられませんが、少し抽象化して実際の 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...
    }
}
于 2009-03-23T03:47:58.563 に答える
1

IContainer インターフェイスをより適切に定義できない限り、キャストを回避することはできません。Marc が言うように、それはインターフェースベースの抽象化の目的を無効にします。

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)
        {
            // ...
        }
    }
}
于 2009-03-23T07:05:53.253 に答える
1

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

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

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

于 2009-03-23T05:27:45.157 に答える