This post is about the idea, not about the implementation. The implementation is crippled, not thread safe, will work only in few scenarios and only if used properly. Do not copy and blindly use this code.
One of unique features of Windsor is that it manages the lifecycle of objects it creates for you. What this means (among other things) is that it will dispose all disposable objects it instantiates. However to do this, it has to keep a reference to these components. Also that means that in order to properly release the components you have to get hold of the container and once you’re done using the components – explicitly release them with the container.
It may be not desirable from your perspective to do it like this. Ideally, you’d rather use your component, call Dispose and then have Windsor release the component. This is not quite possible, since there’s no way by which Windsor can be notified that your component was disposed. Or is there?
Since Dispose is an interface method and Windsor has quite powerful AOP capabilities, we can take advantage of that and intercept the call to Dispose and transparently release our component. Let’s build a disposable component first:
One important thing to notice about this code – Dispose is not implemented virtually. This will make our sample simpler since we won’t have to deal with recursion.
Then we set up the stage:
We’ll discuss the ReleaseComponentInterceptor, which is the gist of this post, in a minute. Let’s first create a test:
Notice that in order for the interceptor to intercept the call to Dispose we need to cast component to IDisposable before calling the method (‘using’ will do that for us). Notice important aspect of this test – it is completely container agnostic. It does not need any kind of explicit nor indirect reference to the container to work and to release the component properly. Let’s now see what happens behind the scenes.
The hero of the day, is the following interceptor:
Most of the time it just sits there and does nothing. However if it detects a call to Dispose, it releases the component from the container, which will in turn invoke the Dispose again (this time on the class, not interface, and since the interface is implemented non-virtually that second call won’t be intercepted), perform all other decommission job for the component as well as all its dependencies and it will release it, so that it can be garbage collected afterwards.
This is just another useful trick, worth knowing if you want to keep your design container agnostic while still reaping full benefits it provides.