Must I release everything when using Windsor?

This is a follow up to my previous post. If you haven’t yet – go and read that one first. I’ll wait.

So where were we? Aha…

In the last post I said, that Windsor (any container in general) creates objects for you, hence it owns them, ergo its responsibility is to properly end their lifetime when they’re no longer needed.

Since as I mentioned in my previous post, Windsor will track your component, it’s a common misconception held by users that in order to properly release all components they must call Release method on the container.

container.Release(myComponent);

How will Windsor know I no longer need an object?

That’s the most important part of this post really, so pay attention.

In Windsor (every container in general) every component has a lifestyle associated with it. In short lifestyle defines the context in which an instance should be reused. If you want to have just single instance of a component in the context of the container, you give the object a singleton lifestyle (which is the default in Windsor). If you want to reuse your object in the context of a web request, you give it a lifestyle of a per-web-request and so on. Now the word context (though overloaded) is important here.

When the context ends?

While some contexts, like web request have a well defined ends that Windsor can detect, that’s not the case for every of them. This brings us to the Release method.

Windsor has a Release method that you use to explicitly tell it “hey, I’m not gonna use this this object anymore.” Although the method is named very imperatively, which would suggest it takes immediate action, it’s not often the case. Quite a lot of time may pass between you call the method and Windsor will get the object destroyed. When the object gets really destroyed is up to its lifestyle manager, and they act differently.

  • Singleton will ignore your call to Release because the instance is global in the scope of the container that created it, and the fact that you don’t need the object in one place does not mean you won’t need it moments later somewhere else. The scope of the singleton lifestyle has a well defined end. Windsor will destroy the singletons when the container itself is being disposed. This also means that you don’t have to Release your singletons – disposing of the container will take care of that.
  • Per-web-request will ignore your call to Release for similar reasons – the object is global in the scope of a web-request. Web request also has a well defined end, so it will wait with destroying the object till the end of the web request and then do all the work necessary. This also means that you don’t have to release your per-web-request components – Windsor can detect end of a web request and release the per-web-request components without and intervention from your side.
  • Per-thread is like singleton in the scope of a thread. Releasing Per-thread components does nothing, they will be released when the container is disposed. This means that in this case as well you don’t have to do anything explicitly about them (except for remembering to dispose the container obviously) ..
  • Pooled components are different. They don’t really have a well defined “end” so you need to return a component to the pool explicitly (that is pass them to container’s Release method), and Windsor (depending on the component and configuration of the pool) may either return the object to the pool, recycle it, or destroy and let it go. Thing is – it matters, and it usually makes sense to return the object to the pool, as soon as possible (think connection pooling in ADO.NET).
  • Transient components are similar to pooled, because there’s no well known end to transient component’s lifetime, and Windsor will not know if you still want to use a component or not, unless you explicitly tell it (by calling Release). Since transient components are by definition non-shared Windsor will immediately destroy the component when you Release it.

And then it gets interesting

If you’re now scratching your head thinking “Does Windsor really puts all the burden of releasing stuff on me?” don’t despair. The reality is – you never have to call Release explicitly in your application code. Here’s why.

You never have to call Release…

Releasing a component releases entire graph. As outlined in previous section, Windsor can detect end of scope for components with most lifetimes. In that case, if you have a per-web-request ShoppingCard component that depends on transient PaymentCalculationService and singleton AuditWriter, when the request ends Windsor will release the shopping card along with both of its dependencies. Since auditwriter is a singleton releasing it will not have any effect (which is what we want) but the transient payment calculator will be releases without you having to do anything explicitly.

You obviously need to structure your application properly for this to work. If you’re abusing the container as service locator than you’re cutting a branch you’re sitting on.

Explicitly…

This also works with typed factories – when a factory is released, all the components that you pulled via the factory will be released as well. However you need to be cautious here – if you’re expecting to be pulling many components during factory’s lifetime (especially if the factory is a singleton) you may end up needlessly holding on to the components for much too long, causing a memory leak.

Imagine you’re writing a web browser, and you have a TabFactory, that creates tabs to display in your browser. The factory would be a singleton in your application, but the tabs it produces would be transient – user can open many tabs, then close them, then open some more, and close them as well. Being a web savvy person you probably know firsthand how quickly memory consumption in a web browser can go up so you certainly don’t want to wait until you dispose of your container to release the factory and release all the tabs it ever created, even the ones that were closed days ago.

More likely you’d want to tell Windsor to release your transient tabs as soon as the user closes it. Easy – just make sure your TabFactory has a releasing method that you call when the tab is closed. The important piece here is that you’d be calling a method on a factory interface that is part of your application code, not method on the container (well – ultimately that will be the result, but you don’t do this explicitly).

UPDATE:

As Mark pointed out in the comment there are certain low level components that act as factories for the root object in our application (IControllerFactory in MVC, IInstanceProvider in WCF etc). If you’re not using typed factories to provide these service and implement them manually pulling stuff from the container, than the other rule (discussed below) applies – release anything you explicitly resolve

In your application code

There are places where you do need to call Release explicitly – in code that extends or modifies the container. For example if you’re using a factory method to create a component by resolving another component first, you should release the other component.

container.Register(
   Component.For<ITaxCalculator>()
      .UsingFactoryMethod(k =>
      {
         var country = k.Resolve<ICountry>(user.CountryCode);
         var taxCalculator = country.GetTaxCalculator();
         k.ReleaseComponent(country);
         return taxCalculator;
      })
   );

This is a code you could place in one of your installers. It is completely artificial but that’s not the point. Point is, we’re using a factory method to provide instances of a component (tax calculator) and for this we’re using another component (country). Remember the rule – You have to release anything you explicitly resolve. We did resolve the country, so unless we are sure that the country is and always will be a singleton or have one of the other self-releasing lifestyles, we should release it before returning the tax calculator.

  • I’m not sure I follow the "never invoke Release explicitly" rule. Sure, in many cases it probably doesn’t matter because for performance reasons we’d like to keep the root of the object graph as long-lived as possible.

    Thus, in a web request, we’d like to scope (say) a FooController as PerWebRequest, in which case everything you wrote holds true.

    However, "never" is such a strong word. What if I (for argument’s sake) were to configure my FooController as Transient or Pooled? If this was the case, I’d need to explicitly Release it at the end of the web request, or it’d hang around leaking memory (particularly if it is disposable).

    Or did I get it all wrong?

  • @Mark,

    did you read the entire post? Especially the "Explicitly…" paragraph?

  • I did, but it mostly talk about Typed Factories… I think perhaps the messaging here is not crystal clear.

    My take is that it’s important to decouple application code from container configuration. In application code, we can’t rely on root components having a certain contextual lifetime. Even if it’s true in v1 of our code, it may change with later versions.

    That said, I think container.Release(foo) should be invoked from the Composition Root’s exit point. For example, in WCF it would be from IInstanceProvider.ReleaseInstance. I don’t know whether you consider that part of the application code or its infrastructure… Obviously, when we use the WCF Facility it’ll be part of the infrastructure, but if not, I think that as application developers, we must at least make sure that an object is released when a contextual scope ends…

  • hmmm

    yes I agree, although I tend to have things like IInstaneProvider or IControllerFactory as typed factories, so that paragraph applies to them. I probably should have made an explicit remark.

    In the root-root (Main, Application_Start/Application_Stop etc) you don’t need to call Release because you call container.Dispose instead.

  • Yes, makes sense. Good thing with the update 🙂

    I was just envisioning hordes of Morts going "but Krzysztof said we should never invoke Release!"… but then again, Morts are not particularly likely to use Windsor 🙂

  • John Simons

    I know you going to scream at me and tell me to go away!
    But why not for transients let the GC do it’s job?
    We all know that we need yo explicitly call Release on transients and half of the time we forget, so why have this burden on the users?
    What is the benefit for the user?

  • John,

    did you read the entire post? Especially the "You never have to call Release…" paragraph?

  • John Simons

    Yes I did, and I do understand the scenario you talk about.
    But there are also the scenarios that Mark refers too, where you have to explicitly resolve/release a component.
    It’s the later scenario that I am more interested in.

  • @John

    I would be interested in a concrete example. I can’t really think of an example where typed factory or proper layering wouldn’t be sufficient.

  • John Simons

    Ok you got me there 🙂
    Yes the type factory would most definitely solve the examples I have.

    But if that is the case, why have resolve/release APIs?
    And I think my original question is still valid, what is Windsor doing with the explicit reference to my transients, specially transients that do not have any dependencies?
    Doesn’t it just store all of them in a List in the Burden implementation.

  • @John – you need Release and Resolve for the few cases I outlined in the post 🙂

    Like I said in the previous post Windsor tracks components so that it can release them.

    "Windsor by default will track objects that themselves have any decommission concerns, are pooled, or any of their dependencies is tracked."

    That means that transients that don’t have decommission concerns and none of their dependencies has any either, won’t be tracked.

  • John Simons

    "That means that transients that don’t have decommission concerns and none of their dependencies has any either, won’t be tracked."

    Is this new in v2.5?
    Because I think in v2.1 they are still tracked.

  • John Simons

    Actually what do you mean "decommission concerns"?
    My transient implements IDisposable, is that a "decommission concerns"

  • @John, have a look at this docs page: stw.castleproject.org/Windsor.Lifecycle.ashx

    I’m not sure if v2.1.1 tracks all components, I suppose the behavior hasn’t changed much between last two versions.

    Yes – Disposal is a decommission concern, Windsor will track the component so that it can dispose of it.

  • @John, in my opinion disposable components are the main reason why this rule should exist for all containers – not just Windsor.

    It would be a Leaky Abstraction if an interface itself implemented IDisposable (although I’m aware that certain BCL interfaces do just that), so consumers don’t know whether the transient IFoo they received implements IDisposable or not. They also don’t know whether it’s transient or something else, so they can’t dispose of it either – even if they decided to break the LSP and explicitly check for that.

    In other words, only the container can tell you whether the IFoo instance should be disposed or not. True to the Hollywood Principle, we don’t query the container to figure out whether the instance should be disposed or not – we just tell it that it we are done with it.

  • Krzysztof, what about this scenario:

    interface IService : IDisposable
    {

    }

    interface IServiceFactory
    {
    IService CreateService();
    void Destroy (IService service);
    }

    and the code:

    using (IService service = serviceFactory.CreateService())
    {

    }

    If I understand your post correctly, I would still need to call serviceFactory.Destroy(service) at the end of the using block?

    If this is true, I find it to be problematic, since it would imply I have to use try finally block in order to be sure the Destroy is really called, even in exceptional cases.

  • Igor, this is a gray area.

    That’s one of the cases that Mark mentioned in one of earlier comments – in principle you don’t own the object, the factory owns it, and the interface should not expose IDisposable at all.

    On the other hand pragmatic benefit of using statement has some advantages in cases like this.

    To make this work you could take an approach similar to kozmic.pl/…/…easing-components-in-windsor.aspx or kozmic.pl/…/…tories-auto-release-and-more.aspx

  • Krzysztof,

    I don’t think the fact a component is available through some Windsor factory should influence its design, since the component could be used elsewhere without IoC (creating it with "new") and you still want it to clean up after itself.

    An idea: what if the typed factory returned a proxy of a component which would implement "factory.Destroy()" in the Dispose method? Then you’d still be able to wrap it in the "using" block. Could this be done using the DynamicProxy?

  • Igor, see the links I enclosed in previous comment.

    I’m not sure about the first paragraph of your last comment. What do you mean that "the fact a component is available through some Windsor factory should influence its design". I’m not proposing it should. Quite the contrary – using the design I outlined without the container would work without issues. Or am I missing your point?

  • Krzysztof,

    My statement was a comment on your statement: "in principle you don’t own the object, the factory owns it, and the interface should not expose IDisposable at all". What I meant was that my interface (let’s say IWebClient) is a general-purpose component which can be used with or without Windsor Castle, so I need it to be IDisposable. I don’t want the fact that some day I’m going to create it through a DI container influence all the other code which uses IWebClient without any containers (which would happen if I made it non-disposable).

    OK, I’ve re-read you posts but I still don’t have the complete picture. If I understand correctly, there’s an interceptor that catches Dispose() methods and releases the component from the container.

    But what happens with IDisposable components created through typed factories? Does the typed factory facility automatically create interceptors for such components and then release them when the Dispose() method is called on a component? Or do I have to add interceptors myself? You posts seem to imply the code is just a brainstorming idea, so I don’t know whether this was later included in the actual Windsor release.

  • I think Nicholas Blumhardt said it best:

    "[An] interface […] generally shouldn’t be disposable. There’s no way for the one defining an interface to foresee all possible implementations of it – you can always come up with a disposable implementation of practically any interface."

    That applies whether or not you resolve that dependency via a container or wire it up manually. That’s why we consider IDisposable interfaces Leaky Abstractions. On the other hand, an implementation can also implement IDisposable. There’s nothing wrong with that.

    However, it’s a tricky subject that I use more than ten pages on in my upcoming book, so it’s hard to provide full guidance in the context of these comments.

  • @Mark,

    If you stick to Nicholas’ philosophy in a DI environment, then you will practically be unable to use the "using" block in your code, since none of the interfaces you’ll be using will be disposable. Then you’ll end up with a lot of try-finally blocks which opens a door to a lot of resource leak bugs.

    How does the fact that the implementation implements IDisposable help you in the situation where you only work through interfaces and not concrete implementations?

    Yes, you can stick IDisposable to practically and interface. But my suggestion is to use a common sense: if your interface represents some kind of a system resource, it’s a good guess it would be wise to provide a mechanism for disposing it. Think files, graphics objects, HTTP connections etc (I’m talking about non-shared resources here, which you would typically define as transient in Windsor). If, on the other hand, it represents some abstract service, you don’t stick IDisposable on it.

    It’s a tricky subject, but I doubt there’s a one-liner solution for it like Nicholas suggests.