访客模式,无需强制转换

发布于 2024-07-15 01:21:57 字数 956 浏览 6 评论 0原文

我有一个关于访客模式的问题,我目前有两个程序集。 我的第一个程序集包含几个接口。

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

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

public interface IContainer : INode
{
}

我的第二个程序集

    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 接口以使用容器。 有任何想法吗? 我应该直接投吗?

干杯

罗汉

i have a question regarding the visitor pattern, I currently have two assemblies. My first assembly contains several interfaces.

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

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

public interface IContainer : INode
{
}

And my second assembly

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

What i want to do is avoid the need to cast in the ContainerVisitor class, I want to reference the Container directly. I cannot change the interface INodeVisitor interface to use Container. Any ideas? Should i just cast?

Cheers

Rohan

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

七分※倦醒 2024-07-22 01:22:01

除非您可以更好地定义 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)
        {
            // ...
        }
    }
}

Unless you can define your IContainer interface better, then you won't be able to avoid the cast. And as Marc says, that defeats the purpose of the interface-based abstraction.

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

With the better defined IContainer, your Visitors won't need to do any casting.

public class ContainerVisitor : INodeVisitor
{
    public void VisitContainer(IContainer container)
    {
        foreach (IComponent component in container.Components)
        {
            // ...
        }
    }
}
稚气少女 2024-07-22 01:22:00

我认为假设它是一个 Container 实例是无效的。 我可以完全有效地编写自己的 IContainer 实现,而您的实现会被它阻塞,从而破坏基于接口的抽象的整个要点。 您也不能(有效地)仅更改 API 来接受 Container (使用显式实现来支持 IContainer),因为我可以使用接口而不是类:

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

如果您想要对基类中的某些内容进行可选支持,那么您将必须使用“as”来检测它。 任何其他的事情都会打破抽象。

I don't think it is valid to assume that it is a Container instance. I could, perfectly validly, write my own IContainer implementation, and your implementation would choke on it, breaking the whole point of interface-based abstraction. You also can't (validly) just change the API to accept Container (using explicit implementation to support IContainer), since I could be using the interface rather than the class:

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

If you want optional support for something from the base-class, then you are going to have to use "as" to detect it. Anything else and you are breaking the abstraction.

旧伤还要旧人安 2024-07-22 01:21:58

强制转换是不可避免的,但您可以对其进行一些抽象,以将其从实际的 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...
    }
}

The cast is unavoidable, but you could abstract it out a bit to remove it from the actual ContainerVisitor class.

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

Now ContainerVisitor can derive from NodeVisitor and avoid the cast

public class ContainerVisitor : NodeVisitor<Container>{
    protected override void VisitContainerTyped(Container container){
        // Do some stuff...
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文