Com o Unity, como injetar uma dependência nomeada em um construtor?

Eu tenho o IRespository registrado duas vezes (com nomes) no seguinte código:

// Setup the Client Repository IOC.Container.RegisterType(new InjectionConstructor()); IOC.Container.RegisterType ("Client", new InjectionConstructor(typeof(ClientEntities))); // Setup the Customer Repository IOC.Container.RegisterType(new InjectionConstructor()); IOC.Container.RegisterType ("Customer", new InjectionConstructor(typeof(CustomerEntities))); IOC.Container.RegisterType(); IOC.Container.RegisterType(); 

Mas quando eu quero resolver isso (para usar o IRepository) eu tenho que fazer uma resolução manual como esta:

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

O que eu gostaria de fazer é resolvê-lo no construtor (assim como o IUnityContainer). Eu preciso de alguma maneira de dizer qual tipo de nome para resolver.

Algo como isto: (NOTA: Não código real)

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

Existe uma maneira de fazer o meu código falso funcionar?

Você pode configurar dependencies com ou sem nomes na API, atributos ou através do arquivo de configuração. Você não mencionou o XML acima, então presumo que esteja usando a API.

Para informar ao contêiner para resolver uma dependência nomeada, você precisará usar um object InjectionParameter. Para o seu exemplo ClientModel, faça o seguinte:

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

Isso informa ao contêiner “Ao resolver ClientModel, chame o construtor que usa um único parâmetro IRepository. Ao resolver esse parâmetro, resolva com o nome ‘Client’ além do tipo.”

Se você quisesse usar atributos, seu exemplo quase funciona, você só precisa mudar o nome do atributo:

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

Esta é uma resposta muito tardia, mas a questão ainda aparece no Google.

Então, de qualquer maneira, 5 anos depois …

Eu tenho uma abordagem bem simples. Normalmente, quando você precisa usar “dependência nomeada”, é porque está tentando implementar algum tipo de padrão de estratégia. Nesse caso, eu simplesmente crio um nível de indireção entre o Unity e o resto do meu código chamado StrategyResolver para não depender diretamente do Unity.

 public class StrategyResolver : IStrategyResolver { private IUnityContainer container; public StrategyResolver(IUnityContainer unityContainer) { this.container = unityContainer; } public T Resolve(string namedStrategy) { return this.container.Resolve(namedStrategy); } } 

Uso:

 public class SomeClass: ISomeInterface { private IStrategyResolver strategyResolver; public SomeClass(IStrategyResolver stratResolver) { this.strategyResolver = stratResolver; } public void Process(SomeDto dto) { IActionHandler actionHanlder = this.strategyResolver.Resolve(dto.SomeProperty); actionHanlder.Handle(dto); } } 

Cadastro:

 container.RegisterType("One"); container.RegisterType("Two"); container.RegisterType(); container.RegisterType(); 

Agora, o mais legal disso é que eu nunca mais terei que tocar o StrategyResolver novamente ao adicionar novas estratégias no futuro.

É muito simples. Muito limpo e mantive a dependência da Unity no mínimo. A única vez que eu tocaria no StrategyResolver seria se eu decidisse mudar a tecnologia de contêineres, o que é muito improvável que aconteça.

Espero que isto ajude!

Edit: Eu realmente não gosto da resposta aceita, porque quando você usa o atributo Dependency no construtor do seu serviço você realmente tem uma dependência do Unity. O atributo Dependency faz parte da biblioteca Unity. Nesse ponto, você também pode passar uma dependência IUnityContainer todos os lugares.

Eu prefiro que minhas classs de serviço dependam de objects que eu possuo completamente, em vez de ter uma dependência rígida em uma biblioteca externa em todo o lugar. Também usando o atributo Dependency torna as assinaturas dos construtores menos limpas e simples.

Além disso, essa técnica permite resolver dependencies nomeadas em tempo de execução sem precisar codificar as dependencies nomeadas no construtor, no arquivo de configuração do aplicativo ou usar InjectionParameter que são todos os methods que exigem saber qual dependência nomeada usar no tempo de design.

Edit (2016-09-19): Para aqueles que podem se perguntar, o contêiner saberá passar por si mesmo quando estiver solicitando IUnityContainer como dependência, conforme mostrado na assinatura do construtor StrategyResolver .

Você deve ser capaz de usar ParameterOverrides

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

edit: Não sei por que você está passando pelo UnityContainer – pessoalmente, nós inserimos nossas dependencies no construtor (o que é “normal” do que eu vi). Mas, independentemente disso, você pode especificar um nome em seus methods RegisterType e Resolve.

 IOC.Container.RegisterType("Client"); IOC.Container.Resolve("Client"); 

e lhe dará o tipo que você registrou para esse nome.

Não faça isso – basta criar uma class ClientRepository : GenericRepository { } e utilizar o sistema Type.