代码之家  ›  专栏  ›  技术社区  ›  Iain Galloway

访问者模式上的变量-默认的no op Visit方法,所以在添加元素类型时不需要更改所有访问者?

  •  2
  • Iain Galloway  · 技术社区  · 14 年前

    我有一组要对其执行操作的元素。经典的“访客”模式不适用于我的情况,因为:-

    • 我的元素类型不稳定。
    • 我想基于接口实现进行访问,我的一些元素实现了需要不同访问者访问的多个接口——这导致在这些类型的Accept方法中的调用不明确。

    我的大多数访客并不关心我的大部分元素。即使我可以使用经典的访问者模式,我绝大多数的访问方法都是无操作的。

    我想要一个访客模式的变体,它看起来像:-

    class Visitor
    {
      // called when I'm Accepted by a ThingICareAbout
      void Visit(ElementICareAbout e)
      {
        // Do whatever needs done.
      }
      // called when I'm Accepted by anything else
      void Visit(Element e)
      {
        // Do nothing.
      }
    }
    

    c# generic method overload not consistent with abstract Visitor pattern

    public interface IAcceptsVisitor
    {
      void Accept<T>( IVisitor<T> v );
    }
    
    public interface IVisitor<T>
    {
      void Visit( T e );
      void Visit<X>( X e );
    }
    
    public class Element : IAcceptsVisitor
    {
      public bool Visited { get; set; }
    
      public Element ()
      {
        Visited = false;
      }
      public void Accept<U>( IVisitor<U> v )
      {
        v.Visit( this );
      }
    }
    
    public class Visitor : IVisitor<Element>
    {
      public void Visit( Element e )
      {
        e.Visited = true;
      }
      public void Visit<X>( X e )
      {
        // Do nothing
      }
    }
    

    但这不起作用,因为编译器只能选择非泛型访问方法,而不是泛型访问方法,如果它在编译时静态地知道它会起作用的话。

    1. 有没有办法使上述的工作?
    2. 还有别的办法吗?

    关于2)我见过 Dynamic Dispatching

    foreach (ThingICareAbout in things.OfType<ThingICareAbout>())
    

    同样值得注意的是:我使用的是.NET 4,所以如果动态类型有帮助,我愿意尝试一下。

    编辑:我根据动态关键字提供了自己的答案。不过,我还是对其他方法非常感兴趣。

    1 回复  |  直到 8 年前
        1
  •  0
  •   Iain Galloway    14 年前

    关于动态关键字,这是我目前所拥有的:-

    public class ThingIDontCareAbout: IAcceptsVisitor
    {
    }
    
    public class ThingICareAbout: IAcceptsVisitor
    {
      public bool Visited { get; set; }
    
      public AdvancedElement()
      {
        Visited = false;
      }
    }
    
    public class Visitor
    {
      public void Visit( IAcceptsVisitor e )
      {
        dynamic d = e;
        this.DynamicVisit( d );
      }
    
      private void DynamicVisit( IAcceptsVisitor e )
      {
        // Do nothing.
      }
    
      private void DynamicVisit( ThingICareAbout e )
      {
        e.Visited = true;
      }
    }
    

    你称之为:-

    Visitor v = new Visitor();
    foreach (IAcceptsVisitor e in things) { v.Visit(e); }
    

    将分析此vs类型检查。我特别想听听你的评论,比较一下:-

    foreach (ThingICareAbout e in things.OfType<ThingICareAbout>()) { ...