C# 杂志/期刊类结构和/或设计模式

C# 杂志/期刊类结构和/或设计模式,c#,xml,class,design-patterns,C#,Xml,Class,Design Patterns,我有一个xml文档,它保存了我们所有的校友杂志 <Magazine> <Volumes> <Volume> <Issues> <Issue> <Sections> <Section> <Articles> <Article>

我有一个xml文档,它保存了我们所有的校友杂志

<Magazine>
  <Volumes>
    <Volume>
      <Issues>
        <Issue>
          <Sections>
            <Section>
              <Articles>
                <Article>
                  <Images>
                    <Image>
                    </Image>
                    ...
                  </Images>
                </Article>
                ...
              </Articles>
            </Section>
            ...
          </Sections>
        </Issue>
        ...
      </Issues>
    </Volume>
    ...
  </Volumes>
</Magazine>

...
...
...
...
...
我为以下内容创建了一个类:卷、期、节、文章和图像

我的问题是:
我应该创建超类和子类的层次结构吗?
i、 e.--图像继承文章继承章节继承问题继承卷

我是否将它们分开,并将泛型集合用作父类的属性?
i、 e.——卷、期、期、节、节、文章、文章、图片

还有什么我完全不知道的?

这些选择的优点/缺点/不足是什么

编辑:
如果我使用的是Issue对象,我还需要知道卷号和卷年,以及每个部分中的文章标题。

如果所有类都有公共属性/方法,则可以使用继承,否则继承将毫无意义


您可以使用从xml文档中获取所需的所有数据,而无需将其映射到类,或者使用映射后继承听起来完全不适合您的情况。只有当域类之间存在自然的层次关系时,才应该使用它。一个经典的例子是

-Employee 
--Contractor
--Permanent
他们仍然需要姓名、地址和类似的方法,如:hire()、fire()、pay()

在您的情况下,没有继承关系,这是一个典型的例子,说明为什么您应该支持组合而不是继承

图像不是文章,但文章有图像。这可以应用于整个结构


这一切都是关于“has a”而不是“is a”。

只有当您知道如何在应用程序中使用此数据、如何存储数据、如何显示数据等时,才能给出准确的答案

通常,文章是一个有用的起点类(类似于博客文章等)。你不需要杂志里面的文章(而是杂志)

//搜索某期杂志中的所有文章
公共IList GetArticles(长ISBN,字符串issueNumber)
{
//实施
}
在某些情况下,您也不需要Section类

public class Article
{
    //can be immutable
    public MagazineIssueView Issue { get; set; }

    public string Author { get; set; }

    public IList<Section> Sections { get; set; }

    public IList<Image> GetAllArticleImages()
    {
        return Sections
            .SelectMany<Section, ContentBlock>(s => s.SectionContent)
            .Where(c => c is Image)
            .Cast<Image>()
            .ToList();
    }
}

public class MagazineIssueView
{
    public long ISBN { get; set; }

    //if you have internal Magazines list, it can be also internal MagazineId
    public string MagazineName { get; set; }

    public DateTime IssueDate { get; set; }

    public string IssueNumber { get; set; }
}

public class Section
{
    public string SectionTitle { get; set; }
    public int Order { get; set; }

    public IList<ContentBlock> SectionContent { get; set; }
}

public abstract class ContentBlock
{
}

public class Image: ContentBlock
{
}

public class Paragraph: ContentBlock
{
}
公共类文章
{
//可以是不变的
公共杂志审查问题{get;set;}
公共字符串作者{get;set;}
公共IList节{get;set;}
公共IList GetAllArticleImages()
{
返回段
.SelectMany(s=>s.SectionContent)
.其中(c=>c是图像)
.Cast()
.ToList();
}
}
公共类杂志评论
{
公共长ISBN{get;set;}
//如果你有内部杂志列表,它也可以是内部杂志
公共字符串MagazineName{get;set;}
公共日期时间发布日期{get;set;}
公共字符串IssueNumber{get;set;}
}
公共课组
{
公共字符串SectionTitle{get;set;}
公共整数顺序{get;set;}
公共IList部分内容{get;set;}
}
公共抽象类ContentBlock
{
}
公共类映像:ContentBlock
{
}
公共类段落:ContentBlock
{
}

谢谢!我知道设计模式/原则在某种程度上会有所帮助。现在。。。去寻找一些关于作曲的教程。不客气。我想说这归结为OOD的原则,而不是设计模式。很有趣。显然,我需要学习林克。感谢linqs链接。我将在.net Repeater控件中列出每个问题,并在请求问题时列出每个问题的信息(包括卷号)(GET)。。。它将显示一个菜单,链接到它的各个部分(如ThisCampus、OtherCampus、CollegeWide、CoverStory、AlumniNews等)和每个部分的文章。当请求一篇文章时,它将显示该文章以及属于该文章的所有图像。你是在建议我省略Volume类而将Issue作为access类吗?这很有道理。。。但是如何以面向对象的方式使用卷信息呢?我把事情复杂化了吗?让卷成为一个接口会更好吗?看起来卷类就是MagazineIssueView类。在这种情况下,IssueNumber属性将是VolumeNumber。作为“view”前缀,我的意思是它只是简短的,仅显示和搜索目的信息,并且在任何情况下,您可能已经使用许多其他属性(例如Price)扩展了类,我想我现在看到了。在我的例子中--使用一个卷类型的属性,我可以使用XmlNode.ParentNode属性设置该属性。这看起来并不是面向对象的,但也许XML->Objects就是这样的。
public class Article
{
    //can be immutable
    public MagazineIssueView Issue { get; set; }

    public string Author { get; set; }

    public IList<Section> Sections { get; set; }

    public IList<Image> GetAllArticleImages()
    {
        return Sections
            .SelectMany<Section, ContentBlock>(s => s.SectionContent)
            .Where(c => c is Image)
            .Cast<Image>()
            .ToList();
    }
}

public class MagazineIssueView
{
    public long ISBN { get; set; }

    //if you have internal Magazines list, it can be also internal MagazineId
    public string MagazineName { get; set; }

    public DateTime IssueDate { get; set; }

    public string IssueNumber { get; set; }
}

public class Section
{
    public string SectionTitle { get; set; }
    public int Order { get; set; }

    public IList<ContentBlock> SectionContent { get; set; }
}

public abstract class ContentBlock
{
}

public class Image: ContentBlock
{
}

public class Paragraph: ContentBlock
{
}