使用Unity如何将一个命名的dependency injection到构造函数中?

我有IRespository注册两次(与名字)在下面的代码:

// Setup the Client Repository IOC.Container.RegisterType<ClientEntities>(new InjectionConstructor()); IOC.Container.RegisterType<IRepository, GenericRepository> ("Client", new InjectionConstructor(typeof(ClientEntities))); // Setup the Customer Repository IOC.Container.RegisterType<CustomerEntities>(new InjectionConstructor()); IOC.Container.RegisterType<IRepository, GenericRepository> ("Customer", new InjectionConstructor(typeof(CustomerEntities))); IOC.Container.RegisterType<IClientModel, ClientModel>(); IOC.Container.RegisterType<ICustomerModel, CustomerModel>(); 

但是,当我想解决这个问题(使用IRepository),我必须做这样的手动解决:

 public ClientModel(IUnityContainer container) { this.dataAccess = container.Resolve<IRepository>(Client); ..... } 

我想要做的就是让它在构造函数中parsing(就像IUnityContainer)。 我需要一些方法来说明哪个命名types要parsing。

像这样的东西:( 注意:不是真正的代码)

 public ClientModel([NamedDependancy("Client")] IRepository dataAccess) { this.dataAccess = dataAccess; ..... } 

有没有办法让我的假代码工作?

您可以在API,属性或configuration文件中configuration具有或不具有名称的依赖关系。 你没有提到上面的XML,所以我假设你正在使用API​​。

要告诉容器parsing一个命名的依赖关系,你需要使用一个InjectionParameter对象。 对于您的ClientModel示例,请执行以下操作:

 container.RegisterType<IClientModel, ClientModel>( new InjectionConstructor( // Explicitly specify a constructor new ResolvedParameter<IRepository>("Client") // Resolve parameter of type IRepository using name "Client" ) ); 

这告诉容器“当parsingClientModel时,调用带有单个IRepository参数的构造函数,parsing该参数时,除了types之外,还要使用名称”Client“来parsing。

如果你想使用属性,你的例子几乎可以工作,你只需要改变属性名称:

 public ClientModel([Dependency("Client")] IRepository dataAccess) { this.dataAccess = dataAccess; ..... } 

这是一个非常晚的反应,但问题仍然显示在谷歌。

所以无论如何,5年后…

我有一个非常简单的方法。 通常当你需要使用“命名依赖”时,这是因为你试图实现某种策略模式。 在这种情况下,我只是简单地在Unity和其余的代码中创build一个间接级别,称为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属性,你实际上有一个很强的依赖。 Dependency属性是Unity库的一部分。 在这一点上,不妨到处传递一个IUnityContainer依赖关系。

我更喜欢让我的服务类依赖于我完全拥有的对象,而不是依赖于外部库。 另外使用Dependency属性使得构造函数的签名更加简洁。

此外,这种技术允许在运行时parsing命名的依赖关系,而不必在构造器,应用程序configuration文件中使用硬编码命名的依赖关系,或者使用InjectionParameter ,这些都是需要知道在devise时使用哪个命名依赖关系的方法。

编辑(2016-09-19):对于那些可能想知道,容器知道要传递自己,当你要求IUnityContainer作为依赖,如StrategyResolver构造函数签名中所示。

你应该可以使用ParameterOverrides

 var repository = IOC.Container.Resolve<IRepository>("Client"); var clientModel = IOC.Container.Resolve<ClientModel>(new ParameterOverrides<ClientModel> { {"dataAccess", repository } } ); 

编辑:我不知道为什么你传递UnityContainer – 个人而言,我们注入我们的依赖到自己的构造函数(这是从我所见过的“正常”)。 但无论如何,您可以在您的RegisterType和Resolve方法中指定一个名称。

 IOC.Container.RegisterType<IRepository, GenericRepository>("Client"); IOC.Container.Resolve<IRepository>("Client"); 

它会给你你注册这个名字的types。