Windsor Container: Como forçar o descarte de um objeto?
-
01-07-2019 - |
Pergunta
Eu tenho um objeto que implementa IDisposable que está registrado com o Windsor Container e eu gostaria de eliminá-lo por isso é Dispose método é chamado e próxima Resolve tempo é chamado ele busca uma nova instância.
O
container.Release(obj);
automaticamente chamar Dispose () imediatamente? Ou eu preciso fazer
obj.Dispose();
container.Release(obj);
Não foi possível encontrar nada na documentação sobre o que exatamente lançamento faz
EDIT: Veja minha resposta abaixo os resultados de testes que fiz. Agora, a questão torna-se, como faço para forçar o recipiente para liberar uma instância de um componente com um ciclo de vida singleton? Isso só precisa ser feito em um lugar e escrever um ciclo de vida personalizado parece muito pesado, é que não há construído em forma de fazê-lo?
Solução
Este é algo que eu acho que as pessoas não estão realmente cientes de quando se trabalha com o recipiente de Windsor - especialmente a freqüência surpreendendo comportamento que componentes transitórios descartáveis ??são realizadas em pelo recipiente para a vida do kernel até que ele está disposto a menos que você liberá-los a si mesmo - embora seja documentado - dê uma olhada aqui - mas para citar rapidamente:
o MicroKernel tem uma política de liberação conectável que pode ligar e implementar algumas encaminhamento para eliminar os componentes. O MicroKernel vem com implementações de três IReleasePolicy:
- AllComponentsReleasePolicy: rastrear todos os componentes para impor a eliminação correcta quando da alienação exemplo MicroKernel
- LifecycledComponentsReleasePolicy: somente rastrear componentes que têm um ciclo de vida decommission associado
- NoTrackingReleasePolicy: não executa qualquer acompanhamento
Você também pode implementar sua própria política de liberação usando a IReleasePolicy interface.
O que você pode achar mais fácil é mudar a política a um NoTrackingReleasePolicy e, em seguida, lidar com a eliminação si mesmo - este é potencialmente arriscado, bem como, mas se os seus estilos de vida são em grande parte transitório (ou se quando o recipiente está disposto a sua aplicação está prestes a fechar de qualquer maneira) provavelmente não é um grande negócio. Lembre-se, porém, que todos os componentes que já foram injetados com o singleton irá realizar uma referência, então você pode acabar causando problemas ao tentar "refresh" seus singletons - parece uma má prática, e me pergunto se talvez você pode evitar ter que fazer isso em primeiro lugar, melhorando a maneira como os aplicativos juntos.
Outras abordagens são para construir um ciclo de vida personalizado com a sua implementação própria decommission (assim liberando o Singleton seria realmente descarte do componente, bem como o ciclo de vida transitória faz).
Como alternativa outra abordagem é ter um decorador para o seu serviço registrado no recipiente com um estilo de vida Singleton, mas o seu serviço subjacente real registrado no recipiente com um estilo de vida transitória - então quando você precisa atualizar o componente apenas dispor do transiente subjacente componente realizada pelo decorador e substituí-la por uma instância recém-resolvido (resolvê-lo usando a chave componentes, em vez do serviço, para evitar o decorador) - isso evita problemas com outros serviços únicos (que não estão sendo "refrescado" ) de agarrar serviços obsoletos que foram eliminados tornando-as inutilizáveis, mas requer um pouco de vazamento etc, para fazê-lo funcionar.
Outras dicas
Depende do estilo de vida do componente que você especificou quando você adicionou-lo ao recipiente.
Você usaria Release () Se o estilo de vida é agrupada. Isso coloca a parte de trás do componente na piscina para a próxima recuperação (o objeto não é destruído, então a eliminação seria ruim)
Se o estilo de vida é transitória, um novo objeto é criado quando você recebe o componente. Neste caso, a disposição é com você, e você não precisa chamar Release
Se o estilo de vida é Thread, o mesmo componente é usado para cada segmento, não destruído.
Se o estilo de vida é Singleton, apenas um componente é criado e não detroyed.
O mais provável é que você está usando componentes transitórios? (Se você estiver preocupado com a eliminá-los em tempo hábil) nesse caso, apenas envolvê-lo com um usando e você está pronto (ou chamar a dispor-se em algum lugar)
using(ISomeService service = container.Resolve<ISomeService>())
{
// Do stuff here
// service.Dispose is automatically called
}
Editar - Sim, a fim de "refresh" ou descarte e recriar o seu singleton você precisa se quer destruir o recipiente ou escrever um ciclo de vida personalizado. Fazendo um ciclo de vida personalizado não é realmente tão difícil e mantém a lógica para fazer isso em um só lugar.
Tudo bem, então eu tenho a execução de testes e parece que Container.Release()
vai causar implicitamente método Dispose()
de um IDisposable para executar somente se o estilo de vida é transitória (este é provavelmente não é exatamente correta, mas o ponto é que ele não vai' fazer uma coisa darn se o estilo de vida é singleton).
Agora, se você chamar Container.Dispose()
ele irá chamar os métodos descartáveis ??também, embora, infelizmente, vai dispor de todo o kernel e você terá que adicionar todos os componentes de volta em:
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
Felizmente no meu caso eu posso dar ao luxo de simplesmente colocar todos os componentes e posso restaurá-los facilmente. No entanto, este é sub-óptima.