Подтвердить что ты не робот

Рекомендации для контейнера МОК

Я использую контейнер Unity IOC, и мне просто интересно, какой лучший лучший способ доступа к контейнеру для нескольких классов.

Должен ли каждый класс иметь член IUnityContainer, а затем передать контейнер в конструктор? Должен ли быть одноэлементный класс с контейнером IOC?

Как насчет разработки asp.net?

Может ли кто-нибудь вести меня в правильном направлении? Благодарю.

4b9b3361

Ответ 1

Поместите контейнер IOC на наивысший уровень/точку входа в процессе и используйте его для ввода зависимостей во всем, что находится под ним.

Ответ 2

IMHO не рекомендуется вводить весь контейнер в класс или иметь локальный сервисный локатор IOC.

Вы хотите видеть из конструктора класса (разрешаете его Foo), какие службы/объекты он использует, чтобы выполнить эту работу. Это улучшает ясность, тестируемость и дегубутивность.

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

Если Foo необходимо создать несколько экземпляров службы электронной почты, лучше создать и ввести EmailServiceFactory (через контейнер IoC), который будет создавать требуемые экземпляры "на лету".

В последнем случае зависимости Foo по-прежнему указаны как можно более конкретные - только те, которые может создать EmailServiceFactory. Если бы я ввел весь контейнер, было бы неясно, какие сервисы, предоставляемые им, являются точными зависимостями Foo.

Теперь, если я позже захочу предоставить разные экземпляры службы электронной почты, я поменяю ее в EmailServiceFactory. Я мог бы поменять местами все factory, если все сервисы, которые он создает, необходимо поменять местами (например, во время тестирования).

Таким образом, за счет создания одного дополнительного класса (factory), я получаю намного более чистый код и не должен беспокоиться о любопытных ошибках, которые могут возникнуть при использовании глобальной статистики. Кроме того, при поставке макетов для тестирования я точно знаю, какие издевательства ему нужны, и не нужно издеваться над целыми типами контейнеров.

Этот подход также имеет то преимущество, что теперь, когда модуль инициализируется (применяется только к Prism/Modularity), ему не нужно регистрировать все типы объектов, которые он снабжает контейнером IoC. Вместо этого он может просто зарегистрировать свой ServiceFactory, который затем поставляет эти объекты.

Чтобы быть ясным, класс инициализации модуля (реализующий IModule) должен по-прежнему получать контейнер IoC в контейнере приложения в своем конструкторе для предоставления услуг, которые потребляются другими модулями, но контейнер не должен вторгаться в классы модулей.

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

Ответ 3

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

IUnityContainer container = new UnityContainer();
container.RegisterInstance<IUnityContainer>(container);

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

private IUnityContainer unityContainer;
[Dependency]
public IUnityContainer UnityContainer
{
    get { return unityContainer; }
    set { unityContainer = value; }
}

таким образом, контейнер вводится всякий раз, когда экземпляр такого класса разрешается/создается.

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

Ответ 4

Если всем вашим объектам нужна ссылка на контейнер, вы должны изучить некоторые из них. Несмотря на то, что все еще предпочтительнее призывать новых повсюду, он по-прежнему расследует ответственность за построение графиков объектов во всем коде. При таком использовании он поражает меня тем, что он используется больше как ServiceLocator вместо контейнера IoC.

Ответ 5

Другим вариантом будет использование CommonServiceLocator, хотя это может быть бессмысленная косвенность, вы можете использовать ServiceLocator.Current как экземпляр, известный всем классам

Ответ 6

У меня есть сообщение на эту тему в моем блоге, где я использую что-то в соответствии с ответом t3mujin. Не стесняйтесь использовать его (не беспокойтесь, что это связано с sharepoint... это не имеет значения):

http://johanleino.spaces.live.com/blog/cns!6BE273C70C45B5D1!213.entry