Вопрос

Я использую Microsoft Unity для внедрения зависимостей и хочу сделать что-то вроде этого:

IDataContext context = _unityContainer.Resolve<IDataContext>();
var repositoryA = _unityContainer.Resolve<IRepositoryA>(context); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(context); //Same instance of context

IDataContext context2 = _unityContainer.Resolve<IDataContext>(); //New instance
var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(context2);

RepositoryA и RepositoryB у обоих есть конструктор, который принимает IDataContext параметр, и я хочу, чтобы Unity инициализировала репозиторий с контекстом, который я ему передаю.Также обратите внимание, что IDataContext не зарегистрирован в Unity (мне не нужны 3 экземпляра IDataContext).

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

Решение

На сегодняшний день они добавили следующую функциональность:

Это в последнем выпуске здесь:

http://unity.codeplex.com/SourceControl/changeset/view/33899

Обсуждение этого здесь:

http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434

Пример:

container.Resolve<IFoo>(new ParameterOverrides<Foo> { { "name", "bar" }, { "address", 42 } });"

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

<2 цента>

Что, если позже вы решите использовать другой сервис, которому требуется больше или меньше, чем просто контекст?

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

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

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

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

«Этот код может взаимодействовать с любым типом репозитория, если он реализует этот интерфейс....Да, и использует контекст данных».

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

</2 цента>

Спасибо ребята ...мой похож на пост "Exist".См. ниже:

        IUnityContainer container = new UnityContainer();
        container.LoadConfiguration();

        _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
        {
            new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
        });

Вы можете использовать InjectionConstructor/InjectionProperty/InjectionMethod в зависимости от вашей архитектуры внедрения в ResolvedParameter< T >("name"), чтобы получить экземпляр предварительно зарегистрированного объекта в контейнере.

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

_unityContainer.RegisterType<IDataContext,DataContextA>("DataContextA", new ContainerControlledLifeTimeManager());
_unityContainer.RegisterType<IDataContext,DataContextB>("DataContextB");

  var repositoryA = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryB = _unityContainer.Resolve<IRepositoryB>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextA")));

  var repositoryA2 = _unityContainer.Resolve<IRepositoryA>(new InjectionConstructor(
new ResolvedParameter<IDataContext>("DataContextB")));

Очень короткий ответ:нет.Unity в настоящее время не имеет возможности передавать в конструктор параметры, которые не являются постоянными или внедряемыми, что мне удалось найти.ИМХО, это самая большая вещь, которой ему не хватает, но я думаю, что это задумано, а не упущено.

Как отмечает Джефф Фриц, теоретически вы могли бы создать собственный менеджер жизненного цикла, который знает, какой экземпляр контекста следует внедрить в различные типы, но это уровень жесткого кодирования, который, похоже, в первую очередь устраняет цель использования Unity или DI.

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

Другая альтернатива, которую вы могли бы использовать (не знаю, хорошая это практика или нет), — создать два контейнера и зарегистрировать экземпляр для каждого:

IDataContext context = _unityContainer.Resolve<IDataContext>();
_unityContainer.RegisterInstance(context);
var repositoryA = _unityContainer.Resolve<IRepositoryA>(); //Same instance of context
var repositoryB = _unityContainer.Resolve<IRepositoryB>(); //Same instance of context


//declare _unityContainer2
IDataContext context2 = _unityContainer2.Resolve<IDataContext>(); //New instance
_unityContainer2.RegisterInstance(context2);
var repositoryA2 = _unityContainer2.Resolve<IRepositoryA>(context2); //will retrieve the other instance

надеюсь, это тоже поможет

NotDan, я думаю, ты сам ответил на свой вопрос в комментариях к lassevk.

Во-первых, я бы использовал LifetimeManager для управления жизненным циклом и количеством экземпляров IDataContext, создаваемых Unity.
http://msdn.microsoft.com/en-us/library/cc440953.aspx

Это звучит как ContainerControlledLifetimeManager object предоставит вам необходимое управление экземплярами.Имея этот LifetimeManager, Unity должна добавить один и тот же экземпляр IDataContext ко всем объектам, которым требуется зависимость IDataContext.

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