Как лучше всего структурировать иерархию классов в C #, чтобы обеспечить доступ к родительским членам класса? - PullRequest
1 голос
/ 19 января 2009

У меня возникла пара вопросов, решающих, как лучше всего описать определенную структуру данных в C # (.NET 3.5).

Мне нужно создать библиотеку классов, которая создает текстовые файлы для ввода программы командной строки. Существуют десятки типов файлов, но большинство из них имеют похожие заголовок, нижний колонтитул и несколько других свойств.

Итак, файл может выглядеть так:

timestamp filename company

....lots of attributes that make up the file body....

footerdetail1 footerdetail2 footerdetail3

Теперь из этих десятков типов файлов на самом деле есть только три уникальные комбинации заголовков и нижних колонтитулов.

Итак, я хочу создать родительский класс, который содержит большинство headerItems и footeritems, а затем реализовать фактические типы файлов в производном классе:

class BaseFileType {

public List<HeaderItems>; 
public List<BodyItems>;   
public List<FooterItems>;
FileType filetype;
String filename;

public BaseFileType1 (FileType filetype,String filename) {

   this.filetype = filetype;
   this.filename = filename;


   // add stuff to the header list
   // add stuff to the footer list


} 

    // some methods to find items in the header/ footer lists

}

class ActualFile1 : BaseFileType {

    ActualFile() {


    //add stuff to the bodyitems list
    }


    //some other generic methods


} 

Дело в том, что я хочу унаследовать конструктор от базового класса для производного класса, но из того, что я прочитал, этого сделать нельзя. Какова лучшая стратегия здесь?

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

ActualFile (): base (родительские параметры)

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

Какие другие альтернативы людям будут работать? Есть одна FileFactory, которая выплевывает классы, содержащие структуру, которая мне нужна?

Ответы [ 3 ]

0 голосов
/ 19 января 2009

Вы можете создать свой базовый класс, который читает верхние и нижние колонтитулы и предоставляет доступ к атрибутам в середине. Затем определите интерфейс, который будут реализованы десятками определенных считывателей атрибутов. Интерфейс может потребовать принятия «базового класса», и каждая реализация будет определять способ чтения содержимого в середине.

На практике у вас есть общий способ чтения общих частей и общий способ доступа к атрибутам. Эти части слабо связаны, поэтому изменения будут менее ограничительными.

0 голосов
/ 19 января 2009

Это похоже на то, что шаблонный метод решит ... (Наконец, место для использования шаблона:)

public abstract class DocumentGenerator
{
  abstract protected void AddHeader();
  abstract protected void AddBody();
  abstract protected void AddFooter();

  // Template Method http://en.wikipedia.org/wiki/Template_method_pattern
  public FileInfo Generate(string sFileName)
  {
    FileInfo f = null;  
    //create file

    // either pass in the file to the below methods or use member vars + an additional write step 
    AddHeader();
    AddBody();
    AddFooter();

    // write out everything to the file
    return f;
  }
}

Далее для каждой из 3 уникальных комбинаций, классы среднего уровня, такие как

abstract public class UniqueHeaderFooterCombination1 : DocumentGenerator
{
  protected override void AddHeader()
  {
    Console.WriteLine("unique combination1 header");
  }
  protected override void AddFooter()
  {
    Console.WriteLine("unique combination1 footer");
  }
}

Наконец, конкретные классы для каждого уникального типа файла

public class LetsSayCSVGenerator : UniqueHeaderFooterCombination1
{
  protected override void AddBody()
  {
    Console.WriteLine("csv body items");
  }
}

Соедините это с фабрикой, чтобы получить правильный тип генератора для FileType, и все готово.

abstract class DocumentGeneratorFactory
{
  public static DocumentGenerator GetGenerator(FileType eFileType)
  {
    switch (eFileType)
    {
      // a hash of FileType => Generator
      default:
        return new LetsSayCSVGenerator();
    }

  }
}

class Program
{
  static void Main(string[] args)
  {
    DocumentGenerator d = DocumentGeneratorFactory.GetGenerator(FileType.CSV);
    FileInfo f = d.Generate("ItsAlive.CSV");
  }
}
0 голосов
/ 19 января 2009

Как вы говорите, конструкторы не наследуются.

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

// base-class
public abstract FileType FileType {get;}

// derived-class
public override FileType FileType {
    get {return FileType.Excel;} // or whatever
}

Обратите внимание, что если вы не задокументируете это очень ясно (и поймете последствия), вы не должны вызывать виртуальный метод (такой как выше) внутри конструктора (так как конструктор производного типа не выполнил пока) - но после этого все в порядке.

Поскольку имя файла на самом деле не зависит от подтипа, я подозреваю, что в любом случае оставлю это как параметр ctor.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...