Domanda

Ho un oggetto che implementa IDisposable registrato con il contenitore Windsor e vorrei eliminarlo in modo che venga chiamato il metodo Dispose e la prossima volta che viene chiamato Resolve recuperi una nuova istanza.

Fa

container.Release(obj); 

chiamare automaticamente Dispose() immediatamente?O devo farlo

obj.Dispose();
container.Release(obj);

Non sono riuscito a trovare nulla nella documentazione su cosa fa esattamente Release

MODIFICARE:Vedi la mia risposta qui sotto per i risultati dei test che ho eseguito.Ora la domanda diventa: come posso forzare il contenitore a rilasciare un'istanza di un componente con un ciclo di vita singleton?Questo deve essere fatto solo in un posto e scrivere un ciclo di vita personalizzato sembra troppo pesante, non esiste un modo integrato per farlo?

È stato utile?

Soluzione

Questo è qualcosa di cui penso che le persone non siano realmente consapevoli quando lavorano con il contenitore Windsor, soprattutto spesso sorprendente comportamento secondo cui i componenti temporanei usa e getta vengono trattenuti dal contenitore per tutta la vita del kernel fino a quando non vengono smaltiti, a meno che non li rilasci tu stesso, sebbene sia documentato, dai un'occhiata Qui - ma per citare velocemente:

Il microkernel ha una politica di rilascio collegabile che può collegare e implementare alcuni routing per smaltire i componenti.Il MicroKernel viene fornito con tre implementazioni IReleasePolicy:

  • Politica di rilascio di tutti i componenti:tenere traccia di tutti i componenti per imporre il corretto smaltimento dopo lo smaltimento dell'istanza MicroKernel
  • Politica di rilascio dei componenti con ciclo di vita:tenere traccia solo dei componenti a cui è associato un ciclo di vita di dismissione
  • Politica di rilascio senza tracciamento:non esegue alcun tracciamento

Puoi anche implementare la tua politica di rilascio utilizzando l'interfaccia IReleasePolicy.

Ciò che potresti trovare più semplice è modificare la policy in a NoTrackingReleasePolicy e poi gestisci tu stesso lo smaltimento: anche questo è potenzialmente rischioso, ma se i tuoi stili di vita sono in gran parte transitori (o se quando il tuo contenitore viene smaltito la tua applicazione sta per chiudersi comunque) probabilmente non è un grosso problema.Ricorda tuttavia che tutti i componenti che sono già stati iniettati con il singleton manterranno un riferimento, quindi potresti finire per causare problemi cercando di "aggiornare" i tuoi singleton - sembra una cattiva pratica, e mi chiedo se forse puoi evitare di doverlo fare fallo in primo luogo migliorando il modo in cui le tue applicazioni vengono assemblate.

Altri approcci consistono nel creare un ciclo di vita personalizzato con la propria implementazione di smantellamento (quindi il rilascio del singleton eliminerebbe effettivamente il componente, proprio come fa il ciclo di vita transitorio).

In alternativa, un altro approccio consiste nell'avere un decoratore per il tuo servizio registrato nel contenitore con uno stile di vita singleton, ma il tuo servizio sottostante effettivo è registrato nel contenitore con uno stile di vita transitorio, quindi quando è necessario aggiornare il componente elimina semplicemente il componente sottostante transitorio conservato dal decoratore e sostituiscilo con un'istanza appena risolta (risolvilo utilizzando la chiave Components, anziché il servizio, per evitare di ottenere il decoratore) - questo evita problemi con altri servizi singleton (che non vengono "aggiornati") dal mantenimento su servizi obsoleti che sono stati eliminati rendendoli inutilizzabili, ma richiedono un po' di casting, ecc.per farlo funzionare.

Altri suggerimenti

Dipende dallo stile di vita del componente specificato quando lo hai aggiunto al contenitore.

Utilizzeresti Release() se lo stile di vita è Pooled.In questo modo il componente viene reinserito nel pool per il successivo recupero (l'oggetto non viene distrutto, quindi lo smaltimento sarebbe sbagliato)

se lo stile di vita è transitorio, quando ottieni il componente viene creato un nuovo oggetto.In questo caso lo smaltimento spetta a te e non è necessario chiamare il Rilascio

Se lo stile di vita è Thread, per ogni thread viene utilizzato lo stesso componente, non distrutto.

Se lo stile di vita è Singleton, solo un componente viene creato e non distrutto.

Molto probabilmente stai utilizzando componenti transitori?(Se sei preoccupato di smaltirli in modo tempestivo) In quel caso, basta avvolgerlo con un uso e sei impostato (o chiama lo smalto da qualche parte)

using(ISomeService service = container.Resolve<ISomeService>())
{
 // Do stuff here
 // service.Dispose is automatically called 
}

Modificare - Sì, per "aggiornare" o eliminare e ricreare il tuo singleton dovresti distruggere il contenitore o scrivere un ciclo di vita personalizzato.Realizzare un ciclo di vita personalizzato non è in realtà così difficile e mantiene la logica per farlo in un unico posto.

Va bene, quindi ho eseguito i test e sembra che Container.Release() CAUSERÀ implicitamente un IDisposable Dispose() metodo da eseguire solo se lo stile di vita è transitorio (questo probabilmente non è esattamente corretto, ma il punto è che non farà nulla se lo stile di vita è singleton).

Ora se chiami Container.Dispose() chiamerà anche i metodi usa e getta, anche se sfortunatamente eliminerà l'intero kernel e dovrai aggiungere nuovamente tutti i componenti:

var container = new WindsorContainer();
container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable
obj.DoSomething();
var obj2 = container.Resolve<MyDisposable>();  // Returns the same instance as obj
obj2.DoSomething();
container.Dispose();  // Will call the Disposable method of obj
// Now the components need to be added back in   
 container.AddComponentWithLifestyle<MyDisposable>(Castle.Core.LifestyleType.Singleton);
var obj3 = container.Resolve<MyDisposable>();  // Create a new instance of MyDisposable

Fortunatamente nel mio caso posso permettermi di eliminare tutti i componenti e posso ripristinarli abbastanza facilmente.Tuttavia questo non è ottimale.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top