Posso passare i parametri del costruttore al metodo Resolve () di Unity?

Sto usando Microsoft Unity per l’iniezione delle dipendenze e voglio fare qualcosa del genere:

IDataContext context = _unityContainer.Resolve(); var repositoryA = _unityContainer.Resolve(context); //Same instance of context var repositoryB = _unityContainer.Resolve(context); //Same instance of context IDataContext context2 = _unityContainer.Resolve(); //New instance var repositoryA2 = _unityContainer.Resolve(context2); 

RepositoryA e RepositoryB hanno entrambi un costruttore che accetta un parametro IDataContext e voglio Unity per inizializzare il repository con il contesto in cui lo passo. Si noti inoltre che IDataContext non è registrato con Unity (non voglio 3 istanze di IDataContext ).

    Ad oggi hanno aggiunto questa funzionalità:

    È nell’ultima goccia qui:

    http://unity.codeplex.com/SourceControl/changeset/view/33899

    Discussione su di esso qui:

    http://unity.codeplex.com/Thread/View.aspx?ThreadId=66434

    Esempio:

     container.Resolve(new ParameterOverrides { { "name", "bar" }, { "address", 42 } });" 

    <2 centesimi>

    Cosa succederebbe se in seguito decidessi di utilizzare un servizio diverso che richiede più o meno solo il contesto?

    Il problema con i parametri del costruttore e IoC è che i parametri sono in definitiva legati al tipo di calcestruzzo utilizzato, anziché essere parte del contratto definito dall’interfaccia del servizio.

    Il mio suggerimento sarebbe di risolvere il contesto, e credo che Unity dovrebbe avere un modo per evitare di build 3 istanze di esso, o dovresti considerare un servizio di fabbrica che ha un modo per build l’object.

    Ad esempio, cosa succederebbe se decidessi in seguito di creare un repository che non si basasse affatto su un database tradizionale, ma invece di utilizzare un file XML per produrre dati fittizi per il test? Come andresti a dare il contenuto XML a quel costruttore?

    IoC si basa sul codice di disaccoppiamento, legando il tipo e la semantica degli argomenti ai tipi concreti, non hai fatto correttamente il disaccoppiamento, c’è ancora una dipendenza.

    “Questo codice può dialogare con qualsiasi tipo di repository possibilmente, purché implementa questa interfaccia …. Oh, e usa un contesto di dati”.

    Ora, so che altri contenitori IoC hanno il supporto per questo, e l’ho avuto anche nella mia prima versione, ma a mio parere, non appartiene alla fase di risoluzione.

    È ansible utilizzare InjectionConstructor / InjectionProperty / InjectionMethod a seconda della propria architettura di iniezione all’interno del parametro ResolvedParameter (“nome”) per ottenere un’istanza di un object preregistrato nel contenitore.

    Nel tuo caso, questo object deve essere registrato con un nome e per la stessa insistenza è necessario ContainerControlledLifeTimeManager () come LifeTimeManager.

     _unityContainer.RegisterType("DataContextA", new ContainerControlledLifeTimeManager()); _unityContainer.RegisterType("DataContextB"); var repositoryA = _unityContainer.Resolve(new InjectionConstructor( new ResolvedParameter("DataContextA"))); var repositoryB = _unityContainer.Resolve(new InjectionConstructor( new ResolvedParameter("DataContextA"))); var repositoryA2 = _unityContainer.Resolve(new InjectionConstructor( new ResolvedParameter("DataContextB"))); 

    Grazie ragazzi … il mio è simile al post di “Exist”. Vedi sotto:

      IUnityContainer container = new UnityContainer(); container.LoadConfiguration(); _activeDirectoryService = container.Resolve(new ResolverOverride[] { new ParameterOverride("activeDirectoryServer", "xyz.adserver.com") }); 

    La risposta molto breve è: no. Unity al momento non ha modo di passare parametri nel costruttore che non sono costanti o iniettati, che sono stato in grado di trovare. IMHO è la cosa più grande che manca, ma penso che sia di progettazione piuttosto che di omissione.

    Come nota Jeff Fritz, in teoria è ansible creare un gestore lifetime personalizzato che sappia quale istanza del contesto iniettare in vari tipi, ma questo è un livello di hard-coding che sembra ovviare allo scopo di usare Unity o DI in primo luogo.

    Potresti fare un piccolo passo indietro rispetto al DI completo e rendere le implementazioni del tuo repository responsabili per stabilire i propri contesti di dati. L’ istanza del contesto può ancora essere risolta dal contenitore, ma la logica per decidere quale utilizzare dovrebbe andare all’implementazione del repository. Non è così puro, certamente, ma eliminerebbe il problema.

    Un’altra alternativa che potresti usare (non so se sia una buona pratica o meno) sta creando due contenitori e registrando un’istanza per ciascuno:

     IDataContext context = _unityContainer.Resolve(); _unityContainer.RegisterInstance(context); var repositoryA = _unityContainer.Resolve(); //Same instance of context var repositoryB = _unityContainer.Resolve(); //Same instance of context //declare _unityContainer2 IDataContext context2 = _unityContainer2.Resolve(); //New instance _unityContainer2.RegisterInstance(context2); var repositoryA2 = _unityContainer2.Resolve(context2); //will retrieve the other instance 

    spero che questo aiuti anche

    NotDan, penso che tu abbia risposto alla tua stessa domanda nei commenti a lassevk.

    Innanzitutto, vorrei utilizzare LifetimeManager per gestire il ciclo di vita e il numero di istanze di IDataContext create da Unity.
    http://msdn.microsoft.com/en-us/library/cc440953.aspx

    Sembra che l’object ContainerControlledLifetimeManager ti fornisca la gestione delle istanze di cui hai bisogno. Con LifetimeManager in posizione, Unity dovrebbe aggiungere la stessa istanza di IDataContext a tutti gli oggetti che richiedono una dipendenza IDataContext.