2

我的项目包含很多类,其中有一堆可以用 XML 文件描述。别担心,这不是 XML 中的逻辑或实现。这是一个游戏,一个例子是可以在 XML、图像文件、动画帧等中定义游戏图块。

我最终会得到一堆看起来像这样的函数:

public static Foo FromXml(ref XmlTextReader reader) { ... }

问题是:这些函数是否应该包含在它们自己的匹配类中,例如上面的一个是 Foo.FromXml。或者,我应该创建一个单独的类来从文件中读取内容吗?这里似乎有两个竞争的一般准则:

  1. 一个班级应该知道关于一件事的一切——它本身。
  2. 一个班级应该只有一个改变的理由。

首先,我不太了解第二个,因为“原因”很模糊。第一个指南建议将每个读者放在相关的类中。第二个说创建一个专门用于读取 xml 文件的类。但利弊是值得商榷的。一方面,每个类都可以包含自己的阅读器,因此没有十几个类被引用。另一方面,每个类都必须包含 System.Xml,如果我更改我的 xml 格式,则可能会在多个文件中发生变化(但我认为这还不算太糟糕)。

我知道最重要的规则是“使用你的大脑”,没有“正确”的解决方案,只有一个好的和有效的解决方案。那么你认为什么会更易读,或者更好,可维护?

编辑:澄清一下,这些类可以完全不相关。既然是游戏,一个可能是精灵动画类,一个可能定义敌人行为,一个可能定义地图布局或属性。所以继承与此无关。

4

2 回答 2

2

FromXml(...) 函数是否相同?假设它们是我会将它放在一个公共库区域中,因为它会使维护它们变得容易得多,因为不会有代码重复。代码也应该很整洁

SomeObject o = (SomeObject)Foo.FromXml(reader);

编辑:或者,可能,创建一些只有 FromXml / ToXml 函数的基本抽象类,然后让所有想要使用这些函数的类都从抽象类继承。

于 2009-12-03T02:52:23.977 回答
1

为所有继承类提供静态基类方法并维护适当的多态性很困难。但是,您可以删除该方法的静态性,并拥有一个 InitializeFromXml 方法,该方法基本上允许您从 xml 填充您的类。虽然我通常不关心公共 Initialize 方法,但这对于多态性往往更好。

这是一个例子。对于像这样的小对象来说有点多(而且我很少真正使用 xml 序列化,但会将其加载到 xml 文档中并提取我需要进行反序列化分配的内容),但是当事情扩展时,被继承,并且通常更多复杂,它允许您重用更多:

public class CustomObject {
    public string AValue { get; set; }
    public bool BValue { get; set; }
    protected IXmlConfiguration Config = new CustomObjectConfig( );

    public virtual string ToXml( ) {
        return Config.ToXml( this );
    }

    public virtual void InitializeFromXml( string xml ) {
        Config.FromXml( xml );
        AValue = ((CustomObjectConfig)Config).A;
        BValue = ((CustomObjectConfig)Config).B;
    }
}

public interface IXmlConfiguration {
    void FromXml( string xml );
    string ToXml( object instance );
}

[XmlRoot( "CustomObject" )]
public class CustomObjectConfig : IXmlConfiguration {
    [XmlElement( "AValue" )]
    public string A { get; set; }
    [XmlAttribute( "bvalue" )]
    public bool B { get; set; }

    public void FromXml( string xml ) {
        byte[] bytes = Encoding.UTF8.GetBytes( xml );
        using ( MemoryStream ms = new MemoryStream( bytes ) ) {
            XmlSerializer xs = new XmlSerializer( typeof( CustomObjectConfig ) );
            CustomObjectConfig cfg = (CustomObjectConfig)xs.Deserialize( ms );
            A = cfg.A;
            B = cfg.B;
        }            
    }

    public string ToXml( object instance ) {
        string xml = null;
        if ( instance is CustomObject ) {
            CustomObject val = (CustomObject)instance;
            A = val.AValue;
            B = val.BValue;
            using ( MemoryStream ms = new MemoryStream( ) ) {
                XmlSerializer xs = new XmlSerializer( typeof( CustomObjectConfig ) );
                xs.Serialize( ms, this );
                ms.Seek( 0, 0 );
                byte[] bytes = ms.ToArray( );
                xml = Encoding.UTF8.GetString( bytes );
            }
        }
        return xml;
    }
}

我喜欢这种方法而不是创建 xml 可序列化对象的原因是因为

  1. xml 序列化通常要求您以一种方式构建类,然后您通常会以另一种方式使用该类。
  2. 这比到处都有大量的 xml 包含属性(可能称为不同的东西)要容易一些,这将允许派生类型的多态序列化。
于 2009-12-03T04:47:21.463 回答