Pregunta

Tengo un objeto que implementa IDisposable que está registrado en el contenedor Windsor y me gustaría deshacerme de él para que se llame al método Dispose y la próxima vez que se llame a Resolve, busque una nueva instancia.

Hace

container.Release(obj); 

¿Llamar automáticamente a Dispose() inmediatamente?¿O necesito hacer

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

No se pudo encontrar nada en la documentación sobre qué hace exactamente Release

EDITAR:Vea mi respuesta a continuación para conocer los resultados de las pruebas que realicé.Ahora la pregunta es: ¿cómo fuerzo al contenedor a liberar una instancia de un componente con un ciclo de vida único?Esto solo debe hacerse en un solo lugar y escribir un ciclo de vida personalizado parece demasiado pesado, ¿no existe una forma integrada de hacerlo?

¿Fue útil?

Solución

Esto es algo de lo que creo que la gente no es realmente consciente cuando trabaja con el contenedor Windsor, especialmente los que a menudo sorprendente comportamiento en el que los componentes transitorios desechables se mantienen en el contenedor durante la vida útil del kernel hasta que se desecha, a menos que los libere usted mismo, aunque está documentado, eche un vistazo aquí - pero para citar rápidamente:

Microkernel tiene una política de liberación conectable que puede conectarse e implementar algún enrutamiento para deshacerse de los componentes.MicroKernel viene con tres implementaciones de IReleasePolicy:

  • Política de lanzamiento de todos los componentes:rastrear todos los componentes para hacer cumplir la eliminación correcta al eliminar la instancia de MicroKernel
  • Política de lanzamiento de componentes con ciclo de vida:realizar un seguimiento únicamente de los componentes que tengan asociado un ciclo de vida de desmantelamiento
  • Política de liberación sin seguimiento:no realiza ningún seguimiento

También puede implementar su propia política de lanzamiento utilizando la interfaz IReleasePolicy.

Lo que podría resultarle más fácil es cambiar la póliza a una Política de liberación sin seguimiento y luego maneje la eliminación usted mismo; esto también es potencialmente riesgoso, pero si sus estilos de vida son en gran medida transitorios (o si cuando se desecha su contenedor su aplicación está a punto de cerrarse de todos modos), probablemente no sea un gran problema.Sin embargo, recuerde que cualquier componente que ya haya sido inyectado con el singleton tendrá una referencia, por lo que podría terminar causando problemas al intentar "actualizar" sus singletons; parece una mala práctica, y me pregunto si tal vez pueda evitar tener que hacerlo. Para ello, en primer lugar, mejore la forma en que se organizan sus aplicaciones.

Otros enfoques son crear un ciclo de vida personalizado con su propia implementación de desmantelamiento (de modo que liberar el singleton en realidad eliminaría el componente, de manera muy similar a como lo hace el ciclo de vida transitorio).

Alternativamente, otro enfoque es tener un decorador para su servicio registrado en el contenedor con un estilo de vida único, pero su servicio subyacente real registrado en el contenedor con un estilo de vida transitorio; luego, cuando necesite actualizar el componente, simplemente deseche el componente subyacente transitorio retenido. por el decorador y reemplácela con una instancia recién resuelta (resuélvala usando la clave de componentes, en lugar del servicio, para evitar obtener el decorador); esto evita problemas con otros servicios singleton (que no se están "actualizando") al mantener en servicios obsoletos que se han eliminado para dejarlos inutilizables, pero que requieren un poco de conversión, etc.para que funcione.

Otros consejos

Depende del estilo de vida del componente que especificó cuando lo agregó al contenedor.

Usarías Release() si el estilo de vida está agrupado.Esto devuelve el componente al grupo para la siguiente recuperación (el objeto no se destruye, por lo que desecharlo sería malo)

si el estilo de vida es transitorio, se crea un nuevo objeto cuando se obtiene el componente.En este caso la disposición depende de usted y no necesita llamar a Release

Si el estilo de vida es Thread, se utiliza el mismo componente para cada thread, no se destruye.

Si el estilo de vida es Singleton, sólo se crea un componente y no se destruye.

¿Lo más probable es que esté utilizando componentes transitorios?(Si le preocupa deshacerse de ellos de manera oportuna) En ese caso, simplemente envuélvelo con un uso y esté configurado (o llame a la eliminación en algún lugar)

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

Editar - Sí, para "actualizar" o eliminar y recrear su singleton necesitaría destruir el contenedor o escribir un ciclo de vida personalizado.En realidad, realizar un ciclo de vida personalizado no es tan difícil y mantiene la lógica para hacerlo en un solo lugar.

Muy bien, he estado realizando pruebas y parece que Container.Release() CAUSARÁ implícitamente un IDisposable Dispose() método para ejecutar solo si el estilo de vida es Transitorio (esto probablemente no sea exactamente correcto, pero el punto es que no servirá de nada si el estilo de vida es único).

Ahora si llamas Container.Dispose() También llamará a los métodos desechables, aunque desafortunadamente eliminará todo el núcleo y tendrás que volver a agregar todos los componentes:

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

Afortunadamente, en mi caso puedo darme el lujo de eliminar todos los componentes y puedo restaurarlos con bastante facilidad.Sin embargo, esto no es óptimo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top