Pregunta

Mi proyecto contiene muchas clases, muchas de las cuales pueden describirse mediante archivos XML.No se preocupe, no es la lógica ni la implementación en XML.Es un juego, y un ejemplo sería que un mosaico de juego se puede definir en XML, el archivo de imagen, cuadros de animación, etc.

Terminaré teniendo un montón de funciones que se ven así:

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

La pregunta es esta:Si estas funciones estuvieran contenidas en su propia clase coincidente, por ejemplo, la de arriba sería Foo.FromXml.¿O debería crear una clase separada para leer cosas de archivos?Parece haber dos pautas generales que compiten aquí:

  1. Una clase debe saber todo sobre una cosa: sí misma.
  2. Una clase sólo debe tener una razón para cambiar.

En primer lugar, no entiendo muy bien la segunda, porque "razón" es bastante vaga.La primera pauta sugiere colocar a cada lector en la clase relacionada.El segundo dice crear una clase dedicada a leer archivos xml.Pero los pros y los contras son discutibles.Por un lado, cada clase podría contener su propio lector, por lo que no se hace referencia a una docena de clases.Por otro lado, cada clase tendría que incluir System.Xml, y si cambio mi formato xml, las cosas podrían cambiar en varios archivos (pero no creo que sea tan malo).

Sé que la regla más importante es "usa tu cerebro" y no existe una solución "correcta", sólo una buena y que funcione.Entonces, ¿qué crees que sería más legible o, mejor aún, mantenible?

editar:Para aclarar, las clases pueden no tener ninguna relación.Dado que es un juego, una puede ser la clase de animación de sprites, se puede definir el comportamiento del enemigo, se puede definir el diseño o las propiedades del mapa.Entonces la herencia no tiene nada que ver con esto.

¿Fue útil?

Solución

¿Las funciones FromXml(...) son idénticas?Suponiendo que lo sean, lo colocaría en un área común de la biblioteca, porque facilitará mucho su mantenimiento ya que no habrá duplicación de código.El código también debería estar limpio.

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

EDITAR: O, posiblemente, crear alguna clase abstracta base que solo tenga las funciones FromXml/ToXml, luego hacer que todas las clases que quieran usar esas funciones hereden de la clase abstracta.

Otros consejos

tener un método de la clase base estática para todas las clases que heredan y el mantenimiento de polimorfismo adecuada es difícil. sin embargo, puede quitar la estática-dad del método, y tener un método InitializeFromXml que esencialmente le permitiría rellenar su clase desde el xml. A pesar de que normalmente no se preocupan por métodos initialize públicas, esto tiende a ser mejor para el polimorfismo.

he aquí un ejemplo. que es un poco demasiado para un objeto pequeño como éste (y rara vez se utilizan realmente serialización XML, sino que cargarlo en un documento XML y sacar lo que necesito para las asignaciones de deserialización), pero cuando la escala de las cosas, son heredados, y en general más compleja, que permite volver a utilizar un poco más:

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

La razón por la que había a favor de este enfoque en lugar de crear objetos serializables XML son porque

  1. serialización XML requiere típicamente la estructura de su clase de una manera, y usted normalmente luego usar ese clase de otra manera.
  2. que es un poco más fácil que tener gran pilas de XML incluyen atributos (Que puede llamarse algo diferente) lados, lo cual permitiría a la serialización polimórfica de derivados tipos.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top