Con Unity come faccio ad iniettare una dipendenza con nome in un costruttore?

Ho registrato l’IRespository due volte (con i nomi) nel seguente codice:

// 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(); 

Ma poi quando voglio risolvere questo (per usare l’IRepository) devo fare una risoluzione manuale come questa:

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

Quello che mi piacerebbe fare è averlo risolto nel costruttore (proprio come IUnityContainer). Ho bisogno di un modo per dire quale tipo di nome risolvere.

Qualcosa del genere: (NOTA: codice non reale)

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

C’è un modo per far funzionare il mio codice falso?

    Puoi configurare dipendenze con o senza nomi nell’API, attributi o tramite il file di configurazione. Non hai menzionato l’XML sopra, quindi presumo che tu stia utilizzando l’API.

    Per dire al contenitore di risolvere una dipendenza denominata, è necessario utilizzare un object InjectionParameter. Per il tuo esempio ClientModel, fai questo:

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

    Questo dice al contenitore “Quando si risolve ClientModel, chiamare il costruttore che accetta un singolo parametro IRepository. Quando si risolve quel parametro, risolvere con il nome” Client “oltre al tipo.”

    Se si desidera utilizzare gli attributi, l’esempio funziona quasi, è sufficiente modificare il nome dell’attributo:

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

    Questa è una risposta molto tarda, ma la domanda si presenta ancora su Google.

    Quindi comunque, 5 anni dopo …

    Ho un approccio abbastanza semplice. Di solito quando devi usare “named dependency” è perché stai cercando di implementare una sorta di modello di strategia. In tal caso, creo semplicemente un livello di riferimento indiretto tra Unity e il resto del mio codice chiamato StrategyResolver per non essere direttamente dipendente da 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); } } 

    Registrazione:

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

    Ora, la cosa bella di questo è che non dovrò mai più toccare StrategyResolver quando aggiungerò nuove strategie in futuro.

    È molto semplice. Molto pulito e ho mantenuto la dipendenza da Unity al minimo indispensabile. L’unica volta che vorrei toccare StrategyResolver è se decido di cambiare la tecnologia del contenitore che è molto improbabile che accada.

    Spero che questo ti aiuti!

    Modifica: non mi piace molto la risposta accettata perché quando si utilizza l’attributo Dependency nel costruttore del servizio in realtà si ha una forte dipendenza da Unity. L’attributo Dependency fa parte della libreria Unity. A quel punto si potrebbe anche passare una dipendenza IUnityContainer ovunque.

    Preferisco che le mie classi di servizio dipendano da oggetti che possiedo completamente, invece di avere una forte dipendenza da una libreria esterna ovunque. Anche l’uso dell’attributo Dependency rende le firme dei costruttori meno pulite e semplici.

    Inoltre, questa tecnica consente di risolvere dipendenze denominate in fase di esecuzione senza dover codificare le dipendenze denominate nel costruttore, nel file di configurazione dell’applicazione o utilizzare InjectionParameter che sono tutti metodi che richiedono di sapere quale dipendenza denominata utilizzare in fase di progettazione.

    Modifica (19-09-2016): per coloro che potrebbero meravigliarsi, il contenitore saprà che passerà da solo quando si richiede IUnityContainer come dipendenza, come mostrato nella firma del costruttore StrategyResolver .

    Dovresti essere in grado di usare ParameterOverrides

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

    edit: Non sono sicuro del motivo per cui stai passando in giro per UnityContainer – personalmente, inseriamo le nostre dipendenze nel costruttore stesso (che è “normale” da quello che ho visto). Ma a prescindere, puoi specificare un nome nei tuoi metodi RegisterType e Resolve.

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

    e ti darà il tipo che hai registrato per quel nome.

    Non farlo: basta creare un class ClientRepository : GenericRepository { } e utilizzare il sistema Type.