Unity (e tutti i contenitori comuni) sono garantiti (da parte dei progettisti) per essere thread-safe (o almeno, sort of) in caso di risolve parallele senza registrazioni. In altre parole, se si separa la fase di registrazione dalla fase di risoluzione e da un punto solo sulla risoluzione dal contenitore, è possibile chiamare Resolve
in parallelo da più thread senza problemi.
In effetti, come best practice, dovresti sempre separare rigorosamente la fase di registrazione dalla fase di risoluzione, perché questo porterà a problemi seri e molto difficili da trovare nelle condizioni di gara.
Questa separazione di quelle fasi è così importante, che alcune librerie DI (come ad esempio Autofac e Simple Injector) Forza questo modello su di voi (dove Semplice Injector è la più rigorosa dei due). La documentazione di Simple Injector contiene un very clear explanation sul perché Simple Injector ti costringe su questo modello e spiega cosa potrebbe accadere nel caso in cui tu potessi cambiare la configurazione. Per citare parte di quella spiegazione qui (ma si dovrebbe assolutamente leggere l'intero spiegazione):
Problemi con thread-sicurezza possono facilmente emergere quando l'utente modifica una registrazione nel corso di una richiesta Web. Se il contenitore consentiva tali modifiche di registrazione durante una richiesta, altre richieste potrebbero direttamente essere modificate da (poiché in generale dovrebbe essere solo un'istanza Contenitore per AppDomain). A seconda di cose come lo stile di vita della registrazione; l'uso delle fabbriche e il modo in cui è strutturato il grafico dell'oggetto , potrebbe essere una reale possibilità che un'altra richiesta di ottenga sia la vecchia che la nuova registrazione. Prendete ad esempio una registrazione temporanea che viene sostituita con una diversa. Se viene eseguito mentre viene risolto un grafico oggetto per un thread diverso mentre il servizio viene iniettato in più punti all'interno del grafico - il grafico conterrà un'istanza diversa di tale astrazione con diverse durate contemporaneamente nello stesso tempo richiesta - e questo è male.
come la vedo io, che the article si collega va più nella differenza tra l'applicazione di Dependency Injection Service Locator anti-pattern e corretto, il che significa che solo l'accesso al contenitore all'interno del vostro Composition Root. Lo scrittore di quell'articolo (Larry Spencer) non è molto chiaro, ma all'interno della sua Composition Root, crea un singolo contenitore Unity e lo usa per tutta la durata dell'intera applicazione.In un certo senso è ancora "globale", ma impedisce l'accesso a tale istanza tramite l'applicazione (perché questo è il pattern Locator di servizio).
Sebbene lo scrittore cerchi di creare un wrapper thread-safe attorno al contenitore Unity, il suo tentativo è ingenuo. Quello che fa è creare un blocco attorno ad ogni metodo Register
e Resolve
. Ciò non solo consentirà un'enorme congestione nelle applicazioni multi-thread, ma non affronterà i problemi di ciò che accade durante la registrazione e la sostituzione delle istanze dopo che i grafici degli oggetti sono già stati compilati e memorizzati nella cache, come spiega la documentazione di Simple Injector e questo Unity question .
questa risposta è semplicemente fantastica, questo è quello che stavo cercando! Grazie! – vmg