Тип проверки, чтобы проанализировать изменение шаблона стратегии


Итак, рассмотрим следующий код:

public class OneConcreteTypeOfOutputFormat 
{
    private Dictionary<Type, IEntityWriter> writers;
    public Dispatcher()
    {
        this.writers = new Dictionary<string, IEntityWriter();
        CreateWriters(writers);
    }

    private void CreateWriters(Dictionary<string, IEntityWriter> writers)
    {
        string nspace = typeof(OneConcreteWriter).Namespace;
        Assembly assembly = Assembly.GetExecutingAssembly();
        foreach (var writer in assembly.GetAllFromNamespace<IEntityWriter>(nspace))
            writers.Add(writer.EntityType.FullName, writer);
    }

    private bool HasWriterForAllPropTypes(IEnumerable<Entity> data)
    {
        return data.All(ent => writers.ContainsKey(ent.GetType().FullName));
    }

    public void WriteEntities(IEnumerable<Entity> entities)
    {
         Require.That(() => HasWriterForAllPropTypes(outputData));
         foreach(Entity entity in entities)
             writers[entity.GetType().FullName].Write(entity);
    }
}

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

Обновление

Обратите внимание, что приведенный выше код полностью обновлен - изменения включают в себя:

  • Писатель добавил код инициализации. Он делегирован на блок-испытанный метод расширения.

  • Изменил имя класса, чтобы отразить, что это только один из различных типов форматов - так это потребует больше, чем просто создание одного писателя для каждой сущности.

  • Добавил немного кода проверки.



469
2
c#
задан 28 июля 2011 в 10:07 Источник Поделиться
Комментарии
3 ответа

Я не знаю, если это будет полезно для вас, но вот один вариант:
Добавить в ваш объект базового класса метода GetWriter. Этот метод должен возвратить IEntityWriter.
Этот IEntityWriter должен иметь метод write() без параметров.

После реализации предприятие будет что-то вроде:

class XXXEntity: Entity
{
public override IEntityWriter GetWriter()
{
return new XXXEntityWriter(this);
}
}

И тогда в вашем примере метод WriteEntities будет

public void WriteEntities(IEnumerable<Entity> entities)
{
foreach(Entity entity in entities)
entity.GetWriter().Write();
}

Подход 'сопоставление' (неважно, если это в коде или в xml-файле) есть пара проблем:
1. Это легко сделать неправильные настройки отображений. Вы можете сопоставить XXXEntity в YYYEntityWriter.
2. Легко забыть добавить EntityWriter при добавлении новой сущности или вы можете забыть, чтобы добавить сопоставление. И это реальная проблема.

Кстати. Судя по описанию задачи, конкретный EntityWriter должны знать о конкретной сущности.
Так что сопоставление не такой гибкий, как кажется, из-за этой явной связи между EntityWriter и лица.
Это не проблема для использования gettype(). Проблема здесь в том, чтобы отделить (скрыть) связей между классами, которые должны работать вместе.

6
ответ дан 28 июля 2011 в 01:07 Источник Поделиться

Я понятия не имею, почему у вас слова "шаблон стратегии" в вашей теме, но то, что вы хотите называется "полиморфное поведение". Есть 2 способа, которые рассматриваются в порядке:


  1. Добавить необходимый метод интерфейса для лица и переопределение/внедрение во всех потомков.

  2. С помощью шаблона разработки посетителя. Идея почти такая же, как в п. 1, но в данном случае было бы достаточно легко добавить больше методов как написать() без необходимости изменения интерфейса объекта интерфейса.

1
ответ дан 29 июля 2011 в 03:07 Источник Поделиться

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

Единственная плохая вещь, которую я вижу в вашем коде заключается в том, что диспетчер знает о всех возможных видах сущность и EntityWriter. Я не вижу никаких проблем с помощью метода gettype () или typeof в мой код. Но это, конечно, лучше, чтобы избавиться от конкретных классов от диспетчера код.

Самое простое-это использовать немного размышлений и класс Activator:


  1. Создать XML-файл, содержащий сопоставления типов сущностей для типа писатель

  2. Создать поле IDictionary в диспетчерскую и заполнить ее данными из XML-файла при запуске, когда экземпляр сущности писателя, полученные с помощью класса Activator

  3. На выполнения всего использовать тот же код, как у вас в WriteEntries, но изменить подпись, чтобы получить лицо, полное имя тип: существо.Метод gettype().Полное имя

Надеюсь, что это помогает.

1
ответ дан 29 июля 2011 в 04:07 Источник Поделиться