C# 如何实现用于生成XML的访问者模式?

C# 如何实现用于生成XML的访问者模式?,c#,java,design-patterns,visitor-pattern,C#,Java,Design Patterns,Visitor Pattern,我有一个包含许多类的复合类结构。由于许多不同的原因(验证、克隆、导出为xml等),需要遍历此结构,因此编写使用访问者模式是有意义的。给定以下类结构 class Owner { public string Name { get; set; } public List<Owned> Liked { get; private set; } public List<Owned> Disliked { get; private set; } pub

我有一个包含许多类的复合类结构。由于许多不同的原因(验证、克隆、导出为xml等),需要遍历此结构,因此编写使用访问者模式是有意义的。给定以下类结构

class Owner
{
    public string Name { get; set; }
    public List<Owned> Liked { get; private set; }
    public List<Owned> Disliked { get; private set; }

    public Owner()
    {
        this.Liked = new List<Owned>();
        this.Disliked = new List<Owned>();
    }
}

class Owned
{
    public string Name { get; set; }
}
类所有者
{
公共字符串名称{get;set;}
公共列表{get;private set;}
不喜欢的公共列表{get;private set;}
公共所有者()
{
this.Liked=newlist();
this.Disliked=新列表();
}
}
阶级所有
{
公共字符串名称{get;set;}
}
如果我想生成这样的XML,应该如何实现这样的访问者模式

<owner>
    <name>Owner 1</name>
    <likedThings>
        <owned>
            <name>Liked thing 1</name>
        </owned>
        <owned>
            <name>Liked thing 2</name>
        </owned>
    </likedThings>
    <dislikedThings>
        <owned>
            <name>Disliked thing 1</name>
        </owned>
        <owned>
            <name>Disliked thing 2</name>
        </owned>
    </dislikedThings>
</owner>

业主1
喜欢的东西1
喜欢的东西2
不喜欢的事情1
不喜欢的事情2
我关心的第一件事是,通常我会有VisitOwner和VisitOwned,这对于验证来说很好,但在XML中,我需要将拥有的对象包装在它们各自喜欢或不喜欢的XML节点中

我关心的第二件事是,对于尚未为组合的任何新部分实现操作的每个现有访问者实现(例如,新属性“List Studythings”)

允许您为问题的双重分派端构建结构,帮助您处理由于模型的继承结构而导致的复杂性。但是,模式的经典形式并不能处理由于模型的组合结构而导致的复杂性,特别是当同一类以不同的容量多次使用时

在您的情况下,解决方案必须解决这两个复杂性-一方面,您拥有
所有者
而不是
所有者
;另一方面,您有
喜欢的
不喜欢的
,以及您计划添加的任何其他内容

处理组合端的任务传统上交给访问者的实现,而不是接口。但是,编译器将无法帮助您找到无法处理新关系的违规者。但是,您可以将访问者模式与结合起来,创建一个处理这两个问题的混合解决方案

以下是您可以执行的操作的框架:

// This is a run-of-the-mill visitor
interface IVisitor {
    void VisitOwner(Owner owner);
    void VisitOwned(Owned owned);
}
// This is a base visitor class; it is abstract
abstract class DefaultVisitor : IVisitor {
    public void VisitOwner(Owner owner) {
        BeginOwner(owner);
        BeginLiked();
        foreach (var owned in owner.Liked) {
            owned.Accept(this);
        }
        EndLiked();
        BeginDisliked();
        foreach (var owned in owner.Disliked) {
            owned.Accept(this);
        }
        EndDisliked();
        EndOwner(owner);
    }
    public void VisitOwned(Owned owned) {
        BeginOwned(owned);
        EndOwned(owned);
    }
    public abstract void BeginOwner(Owner owner);
    public abstract void EndOwner(Owner owner);
    public abstract void BeginOwned(Owned owned);
    public abstract void EndOwned(Owned owned);
    public abstract void BeginLiked();
    public abstract void EndLiked();
    public abstract void BeginDisliked();
    public abstract void EndDisliked();
}
这样构造代码的好处是编译器现在可以检查
DefaultVisitor
的实现是否存在所有抽象方法;缺点是这些实现必须提供八个实现,而不是两个