Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windsor Container: How to force dispose of an object?

I have an object that implements IDisposable that is registered with the Windsor Container and I would like to dispose of it so it's Dispose method is called and next time Resolve is called it fetches a new instance.

Does

container.Release(obj); 

automatically call Dispose() immediately? Or do I need to do

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

Couldn't find anything in the documentation on what exactly Release does

EDIT: See my answer below for the results of tests I ran. Now the question becomes, how do I force the container to release an instance of a component with a singleton lifecycle? This only needs to be done in one place and writing a custom lifecycle seems far too heavyweight, is there no built in way of doing it?

like image 440
George Mauer Avatar asked Sep 17 '08 16:09

George Mauer


1 Answers

This is something I think people aren't really aware of when working with the Windsor container - especially the often surprising behavior that disposable transient components are held onto by the container for the lifetime of the kernel until it's disposed unless you release them yourself - though it is documented - take a look here - but to quickly quote:

the MicroKernel has a pluggable release policy that can hook up and implement some routing to dispose the components. The MicroKernel comes with three IReleasePolicy implementations:

  • AllComponentsReleasePolicy: track all components to enforce correct disposal upon the MicroKernel instance disposal
  • LifecycledComponentsReleasePolicy: only track components that have a decommission lifecycle associated
  • NoTrackingReleasePolicy: does not perform any tracking

You can also implement your own release policy by using the interface IReleasePolicy.

What you might find easier is to change the policy to a NoTrackingReleasePolicy and then handle the disposing yourself - this is potentially risky as well, but if your lifestyles are largely transient (or if when your container is disposed your application is about to close anyway) it's probably not a big deal. Remember however that any components which have already been injected with the singleton will hold a reference, so you could end up causing problems trying to "refresh" your singletons - it seems like a bad practice, and I wonder if perhaps you can avoid having to do this in the first place by improving the way your applications put together.

Other approaches are to build a custom lifecycle with it's own decommission implementation (so releasing the singleton would actually dispose of the component, much like the transient lifecycle does).

Alternatively another approach is to have a decorator for your service registered in the container with a singleton lifestyle, but your actual underlying service registered in the container with a transient lifestyle - then when you need to refresh the component just dispose of the transient underlying component held by the decorator and replace it with a freshly resolved instance (resolve it using the components key, rather then the service, to avoid getting the decorator) - this avoids issues with other singleton services (which aren't being "refreshed") from holding onto stale services which have been disposed of making them unusable, but does require a bit of casting etc. to make it work.

like image 106
Bittercoder Avatar answered Nov 16 '22 00:11

Bittercoder