2009-12-03 4 views
2

В моем проекте много классов, куча которых может быть описана файлами XML. Не волнуйтесь, это не логика или реализация в XML. Это игра, и примером могло бы быть то, что игровая плитка может быть определена в XML, файле изображения, кадрах анимации и т. Д.Должен ли я создать для этого отдельный класс?

Я собираюсь в конечном итоге иметь кучу функций, которые выглядят так:

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

вопрос заключается в следующем: если эти функции должны содержаться в своем собственном классе соответствия, например, один выше будет Foo.FromXml. Или я должен сделать отдельный класс для чтения вещей из файлов? Кажется, что здесь есть два общих принципа:

  1. Класс должен знать все об одной вещи - самой.
  2. У класса должна быть только одна причина для изменения.

Прежде всего, я не совсем понимаю второй, потому что «разум» довольно расплывчатый. В первом руководстве предлагается каждый читатель в соответствующем классе. Второй говорит, чтобы сделать один класс, посвященный чтению xml-файлов. Но плюсы и минусы спорны. С одной стороны, каждый класс может содержать свой собственный читатель, поэтому не существует десятка классов, на которые они ссылаются. С другой стороны, каждый класс должен включать System.Xml, и если я изменю свой XML-формат, все может измениться в нескольких файлах (но я не думаю, что это слишком плохо).

Я знаю, что самое важное правило - «использовать свой мозг», и нет такого понятия, как «правильное» решение, только хорошее и работающее. Итак, что, по вашему мнению, было бы более читаемым или, еще лучше, поддерживаемым?

изменить: уточнить, классы могут быть абсолютно не связаны. Поскольку это игра, может быть класс анимации спрайтов, можно определить поведение противника, можно определить макет карты или свойства. Таким образом, наследование не имеет к этому никакого отношения.

+0

Рассмотрите проект, в котором методы не являются статическими, и где они не используют параметры ref. Refs, как правило, являются запахами кода (почему вы изменяете ссылку?), А статические методы тесно соединяют вызывающих абонентов с этим классом. – TrueWill

ответ

2

Являются ли функции FromXml (...) идентичными? Предполагая, что это я, я бы разместил его в общей библиотечной области, потому что он будет поддерживать их намного проще, так как не будет дублирования кода. Код должен еще быть аккуратным слишком

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

EDIT: Или, возможно, сделать какой-то базовый абстрактный класс, который только есть в/ToXml функции FromXml, то есть все классы, которые хотят, чтобы использовать эти функции наследуют от абстрактного класс.

+0

+1: Кроме того, если они редко меняются, бросьте их в библиотеку, которая также является отдельной сборкой/проектом и просто импортирует dll. Сокращает время сборки. –

+0

Реф из-за того, что xml, загружаемый для объекта, может быть не весь файл. Это может быть фрагмент файла, который уже читается другим методом загрузки. Таким образом, на полпути через чтение xml, один метод может увидеть «о, здесь есть спрайт» и передать управление методу загрузки спрайтов. Это похоже на включение. – Tesserex

+0

Извините, это был комментарий на вопрос, а не здесь. – Tesserex

1

, имеющий статический метод базового класса для всех наследующих классов &, что является сложным для поддержания правильного полиморфизма. Однако вы могли бы удалить статичность метода и иметь метод InitializeFromXml, который по существу позволит вам заполнить ваш класс из xml. Хотя я обычно не забочусь о публичных методах инициализации, это, как правило, лучше для полиморфизма.

вот пример.это немного для небольшого объекта, подобного этому (и я редко когда-либо использовал сериализацию 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 включают в себя атрибуты (можно назвать что-то другое) везде что позволило бы полиморфных сериализаций производных типов.
Смежные вопросы