Могу ли я передать параметры конструктора в метод Unol Resolve ()? - PullRequest
83 голосов
/ 24 апреля 2009

Я использую 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).

Ответы [ 7 ]

67 голосов
/ 22 сентября 2009

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

Это в последней капле здесь:

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 } });"
35 голосов
/ 24 апреля 2009

<2 цента>

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

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

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

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

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

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

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

</ 2 цента>

6 голосов
/ 29 октября 2014

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

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

        _activeDirectoryService = container.Resolve<IActiveDirectoryService>(new ResolverOverride[]
        {
            new ParameterOverride("activeDirectoryServer", "xyz.adserver.com")
        });
5 голосов
/ 28 апреля 2010

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

В вашем случае этот Объект должен быть зарегистрирован под Именем, и для того же страхового полиса вам нужен 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")));
3 голосов
/ 29 апреля 2009

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

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

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

1 голос
/ 15 мая 2009

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

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

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

0 голосов
/ 28 апреля 2009

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

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

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

...