Это очень поздний ответ, но вопрос все еще появляется в Google.
Так что в любом случае, 5 лет спустя ...
У меня довольно простой подход.Обычно, когда вам нужно использовать «именованную зависимость», это потому, что вы пытаетесь реализовать какой-то шаблон стратегии.В этом случае я просто создаю уровень косвенности между Unity и остальной частью моего кода, называемый StrategyResolver
, чтобы не зависеть напрямую от Unity.
public class StrategyResolver : IStrategyResolver
{
private IUnityContainer container;
public StrategyResolver(IUnityContainer unityContainer)
{
this.container = unityContainer;
}
public T Resolve<T>(string namedStrategy)
{
return this.container.Resolve<T>(namedStrategy);
}
}
Использование:
public class SomeClass: ISomeInterface
{
private IStrategyResolver strategyResolver;
public SomeClass(IStrategyResolver stratResolver)
{
this.strategyResolver = stratResolver;
}
public void Process(SomeDto dto)
{
IActionHandler actionHanlder = this.strategyResolver.Resolve<IActionHandler>(dto.SomeProperty);
actionHanlder.Handle(dto);
}
}
Регистрация:
container.RegisterType<IActionHandler, ActionOne>("One");
container.RegisterType<IActionHandler, ActionTwo>("Two");
container.RegisterType<IStrategyResolver, StrategyResolver>();
container.RegisterType<ISomeInterface, SomeClass>();
Теперь приятно отметить, что мне больше никогда не придется прикасаться к StrategyResolver при добавлении новых стратегий в будущем.
Это очень просто.Очень чисто и я держал зависимость от Unity до строгого минимума.Единственный раз, когда я коснусь StrategyResolver, это если я решу изменить контейнерную технологию, что вряд ли произойдет.
Надеюсь, это поможет!
Редактировать: Мне не очень нравятся принятыеответ, потому что когда вы используете атрибут Dependency
в конструкторе вашего сервиса, вы на самом деле сильно зависите от Unity.Атрибут Dependency
является частью библиотеки Unity.В этот момент вы могли бы также пропустить зависимость IUnityContainer
везде.
Я предпочитаю, чтобы мои классы обслуживания зависели от объектов, которыми я полностью владею, вместо жесткой зависимости от внешней библиотеки повсеместно.Кроме того, использование атрибута Dependency
делает подписи конструкторов менее понятными и простыми.
Кроме того, этот метод позволяет разрешать именованные зависимости во время выполнения без необходимости жестко кодировать именованные зависимости в конструкторе, в файле конфигурации приложения или использоватьInjectionParameter
- это все методы, которые требуют знать, какую именованную зависимость использовать во время разработки.
Редактировать (2016-09-19): Для тех, кто может задаться вопросом, контейнер будет знать, что он пропустит себя, когда выIUnityContainer
запрашивают *1032* как зависимость, как показано в сигнатуре конструктора StrategyResolver
.
Редактировать (2018-10-20): вот другой способ, просто с использованием фабрики:
public class SomeStrategyFactory : ISomeStrategyFactory
{
private IStrategy _stratA;
private IStrategy _stratB;
public SomeFactory(IStrategyA stratA, IStrategyB stratB)
{
_stratA = stratA;
_stratB = stratB;
}
public IStrategy GetStrategy(string namedStrategy){
if (namedStrategy == "A") return _stratA;
if (namedStrategy == "B") return _stratB;
}
}
public interface IStrategy {
void Execute();
}
public interface IStrategyA : IStrategy {}
public interface IStrategyB : IStrategy {}
public class StrategyA : IStrategyA {
public void Execute(){}
}
public class StrategyB : IStrategyB {
public void Execute() {}
}
Использование:
public class SomeClass : ISomeClass
{
public SomeClass(ISomeStrategyFactory strategyFactory){
IStrategy strat = strategyFactory.GetStrategy("HelloStrategy");
strat.Execute();
}
}
Регистрация:
container.RegisterType<ISomeStrategyFactory, SomeStrategyFactory>();
container.RegisterType<IStrategyA, StrategyA>();
container.RegisterType<IStrategyB, StrategyB>();
container.RegisterType<ISomeClass, SomeClass>();
Это второе предложение то же самое, но с использованием шаблона фабричного дизайна.
Надеюсь, это поможет!