我应该为此创建一个单独的类吗?

时间:2009-12-03 02:47:30

标签: c# file-io class-design static-methods

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

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

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

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

  1. 一个班级应该了解一件事 - 本身。
  2. 一个班级应该有一个改变的理由。
  3. 首先,我并不真正了解第二个,因为“理由”很模糊。第一条准则建议将每位读者放入相关课程。第二个说要创建一个专门用于读取xml文件的类。但利弊是值得商榷的。一方面,每个类都可以包含自己的读者,因此没有引用十几个类。另一方面,每个类都必须包含System.Xml,如果我改变我的xml格式,事情可能会在多个文件中发生变化(但我认为这不太糟糕)。

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

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

2 个答案:

答案 0 :(得分:2)

FromXml(...)功能是否相同?假设它们是我将它放在一个公共的库区域,因为它将使它们更容易维护,因为没有代码重复。代码应该仍然整洁

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

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

答案 1 :(得分: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包含属性 (可称为不同的东西) 到处都可以 派生的多态序列化 类型。