Вопрос

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

abstract class Field {
  public Field( ICommandStack commandStack ) {}
}

abstract class Entity {
  public readonly Collection<Field> Fields { get; }
}

class EntityA {
  public EntityA( ICommandStack commandStack ) {
    Fields.Add( new StringField( commandStack ) );
  }
}

class EntitiyB {
  public EntityB( ICommandStack commandStack ) {
    Fields.Add( new IntField( commandStack ) );
    Fields.Add( new IntField( commandStack ) );
    Fields.Add( new IntField( commandStack ) );
  }
}

Итак, моя проблема - создание полей в конструкторах. Мои поля нуждаются в ICommandStack, а сущности - нет. Они получают только ICommandStack для создания своих полей.

Может быть проще запросить поля в качестве аргумента в конструкторе каждого объекта. Но количество полей может быть> 10 для отдельных сущностей. Я не хочу создавать конструкторы с таким количеством параметров.

Таким образом, моя идея состояла в том, чтобы передать FieldFactory Entites:

class EntityA {
  public EntityA( IFieldFactory fieldFactory ) {
    // create as many fields as needed via the factory
    Fields.Add( fieldFactory.CreateStringField() );
  }
}

По крайней мере (для Entity) ненужного ICommandStack теперь нет. Но как FieldFactory создает поле? Он может только внедрить ICommandStack, но создание полей все еще должно выполняться с помощью ключевого слова «new». Или я должен дать фабрике ссылку на мой DI-контейнер?

Что такое хорошее дизайнерское решение здесь?

Это было полезно?

Решение

Я бы использовал FieldFactory и внедрил бы фабрику со ссылкой на контейнер (или на интерфейс, который абстрагирует его, если вы недовольны сильной зависимостью от вашего контейнера).

В противном случае, это черепахи вниз. Вам нужен какой-то объект, чтобы запросить у контейнера новый экземпляр в какой-то момент. Если вы хотите, чтобы ваши поля вводились с помощью DI, вам нужно попросить контейнер создать их или вас.

Подводя итог, я бы пошел с завода.

Другие советы

В Spring (и Spring.NET) существует концепция " области прототипа " бобы / объект.

http: / /static.springframework.org/spring/docs/2.0.x/reference/beans.html#beans-factory-scopes-prototype

Вместо того, чтобы вставлять фиксированные объекты и соединять их все вместе, область действия прототипа будет создавать новый экземпляр объекта каждый раз, когда его запрашивают из контейнера IoC. Я не уверен, какой DI-фреймворк вы используете, но он может иметь что-то похожее.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top