Must I release everything when using Windsor?

This is a fol­low up to my pre­vi­ous 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 Wind­sor (any con­tainer in gen­eral) cre­ates objects for you, hence it owns them, ergo its respon­si­bil­ity is to prop­erly end their life­time when they’re no longer needed.

Since as I men­tioned in my pre­vi­ous post, Wind­sor will track your com­po­nent, it’s a com­mon mis­con­cep­tion held by users that in order to prop­erly release all com­po­nents they must call Release method on the container.

container.Release(myComponent);

How will Wind­sor know I no longer need an object?

That’s the most impor­tant part of this post really, so pay attention.

In Wind­sor (every con­tainer in gen­eral) every com­po­nent has a lifestyle asso­ci­ated with it. In short lifestyle defines the con­text in which an instance should be reused. If you want to have just sin­gle instance of a com­po­nent in the con­text of the con­tainer, you give the object a sin­gle­ton lifestyle (which is the default in Wind­sor). If you want to reuse your object in the con­text of a web request, you give it a lifestyle of a per-web-request and so on. Now the word con­text (though over­loaded) is impor­tant here.

When the con­text ends?

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

Wind­sor has a Release method that you use to explic­itly tell it “hey, I’m not gonna use this this object any­more.” Although the method is named very imper­a­tively, which would sug­gest it takes imme­di­ate action, it’s not often the case. Quite a lot of time may pass between you call the method and Wind­sor will get the object destroyed. When the object gets really destroyed is up to its lifestyle man­ager, and they act differently.

  • Sin­gle­ton will ignore your call to Release because the instance is global in the scope of the con­tainer that cre­ated it, and the fact that you don’t need the object in one place does not mean you won’t need it moments later some­where else. The scope of the sin­gle­ton lifestyle has a well defined end. Wind­sor will destroy the sin­gle­tons when the con­tainer itself is being dis­posed. This also means that you don’t have to Release your sin­gle­tons – dis­pos­ing of the con­tainer will take care of that.
  • Per-web-request will ignore your call to Release for sim­i­lar rea­sons – the object is global in the scope of a web-request. Web request also has a well defined end, so it will wait with destroy­ing the object till the end of the web request and then do all the work nec­es­sary. This also means that you don’t have to release your per-web-request com­po­nents – Wind­sor can detect end of a web request and release the per-web-request com­po­nents with­out and inter­ven­tion from your side.
  • Per-thread is like sin­gle­ton in the scope of a thread. Releas­ing Per-thread com­po­nents does noth­ing, they will be released when the con­tainer is dis­posed. This means that in this case as well you don’t have to do any­thing explic­itly about them (except for remem­ber­ing to dis­pose the con­tainer obviously) ..
  • Pooled com­po­nents are dif­fer­ent. They don’t really have a well defined “end” so you need to return a com­po­nent to the pool explic­itly (that is pass them to container’s Release method), and Wind­sor (depend­ing on the com­po­nent and con­fig­u­ra­tion of the pool) may either return the object to the pool, recy­cle it, or destroy and let it go. Thing is — it mat­ters, and it usu­ally makes sense to return the object to the pool, as soon as pos­si­ble (think con­nec­tion pool­ing in ADO.NET).
  • Tran­sient com­po­nents are sim­i­lar to pooled, because there’s no well known end to tran­sient component’s life­time, and Wind­sor will not know if you still want to use a com­po­nent or not, unless you explic­itly tell it (by call­ing Release). Since tran­sient com­po­nents are by def­i­n­i­tion non-shared Wind­sor will imme­di­ately destroy the com­po­nent when you Release it.

And then it gets interesting

If you’re now scratch­ing your head think­ing “Does Wind­sor really puts all the bur­den of releas­ing stuff on me?” don’t despair. The real­ity is – you never have to call Release explic­itly in your appli­ca­tion code. Here’s why.

You never have to call Release…

Releas­ing a com­po­nent releases entire graph. As out­lined in pre­vi­ous sec­tion, Wind­sor can detect end of scope for com­po­nents with most life­times. In that case, if you have a per-web-request Shop­ping­Card com­po­nent that depends on tran­sient Pay­ment­Cal­cu­la­tion­Ser­vice and sin­gle­ton AuditWriter, when the request ends Wind­sor will release the shop­ping card along with both of its depen­den­cies. Since auditwriter is a sin­gle­ton releas­ing it will not have any effect (which is what we want) but the tran­sient pay­ment cal­cu­la­tor will be releases with­out you hav­ing to do any­thing explicitly.

You obvi­ously need to struc­ture your appli­ca­tion prop­erly for this to work. If you’re abus­ing the con­tainer as ser­vice loca­tor than you’re cut­ting a branch you’re sit­ting on.

Explic­itly…

This also works with typed fac­to­ries – when a fac­tory is released, all the com­po­nents that you pulled via the fac­tory will be released as well. How­ever you need to be cau­tious here – if you’re expect­ing to be pulling many com­po­nents dur­ing factory’s life­time (espe­cially if the fac­tory is a sin­gle­ton) you may end up need­lessly hold­ing on to the com­po­nents for much too long, caus­ing a mem­ory leak.

Imag­ine you’re writ­ing a web browser, and you have a Tab­Fac­tory, that cre­ates tabs to dis­play in your browser. The fac­tory would be a sin­gle­ton in your appli­ca­tion, but the tabs it pro­duces would be tran­sient – user can open many tabs, then close them, then open some more, and close them as well. Being a web savvy per­son you prob­a­bly know first­hand how quickly mem­ory con­sump­tion in a web browser can go up so you cer­tainly don’t want to wait until you dis­pose of your con­tainer to release the fac­tory and release all the tabs it ever cre­ated, even the ones that were closed days ago.

More likely you’d want to tell Wind­sor to release your tran­sient tabs as soon as the user closes it. Easy – just make sure your Tab­Fac­tory has a releas­ing method that you call when the tab is closed. The impor­tant piece here is that you’d be call­ing a method on a fac­tory inter­face that is part of your appli­ca­tion code, not method on the con­tainer (well – ulti­mately that will be the result, but you don’t do this explicitly).

UPDATE:

As Mark pointed out in the com­ment there are cer­tain low level com­po­nents that act as fac­to­ries for the root object in our appli­ca­tion (ICon­troller­Fac­tory in MVC, IIn­stan­ce­Provider in WCF etc). If you’re not using typed fac­to­ries to pro­vide these ser­vice and imple­ment them man­u­ally pulling stuff from the con­tainer, than the other rule (dis­cussed below) applies — release any­thing you explic­itly resolve

In your appli­ca­tion code

There are places where you do need to call Release explic­itly – in code that extends or mod­i­fies the con­tainer. For exam­ple if you’re using a fac­tory method to cre­ate a com­po­nent by resolv­ing another com­po­nent 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 com­pletely arti­fi­cial but that’s not the point. Point is, we’re using a fac­tory method to pro­vide instances of a com­po­nent (tax cal­cu­la­tor) and for this we’re using another com­po­nent (coun­try). Remem­ber the rule – You have to release any­thing you explic­itly resolve. We did resolve the coun­try, so unless we are sure that the coun­try is and always will be a sin­gle­ton or have one of the other self-releasing lifestyles, we should release it before return­ing the tax calculator.

  • http://blog.ploeh.dk/ Mark See­mann

    I'm not sure I fol­low the "never invoke Release explic­itly" rule. Sure, in many cases it prob­a­bly doesn't mat­ter because for per­for­mance rea­sons 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 FooCon­troller as Per­We­bRe­quest, in which case every­thing you wrote holds true.

    How­ever, "never" is such a strong word. What if I (for argument's sake) were to con­fig­ure my FooCon­troller as Tran­sient or Pooled? If this was the case, I'd need to explic­itly Release it at the end of the web request, or it'd hang around leak­ing mem­ory (par­tic­u­larly if it is disposable).

    Or did I get it all wrong?

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    @Mark,

    did you read the entire post? Espe­cially the "Explic­itly…" paragraph?

  • http://blog.ploeh.dk/ Mark See­mann

    I did, but it mostly talk about Typed Fac­to­ries… I think per­haps the mes­sag­ing here is not crys­tal clear.

    My take is that it's impor­tant to decou­ple appli­ca­tion code from con­tainer con­fig­u­ra­tion. In appli­ca­tion code, we can't rely on root com­po­nents hav­ing a cer­tain con­tex­tual life­time. 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 Com­po­si­tion Root's exit point. For exam­ple, in WCF it would be from IInstanceProvider.ReleaseInstance. I don't know whether you con­sider that part of the appli­ca­tion code or its infra­struc­ture… Obvi­ously, when we use the WCF Facil­ity it'll be part of the infra­struc­ture, but if not, I think that as appli­ca­tion devel­op­ers, we must at least make sure that an object is released when a con­tex­tual scope ends…

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    hmmm

    yes I agree, although I tend to have things like IIn­stane­Provider or ICon­troller­Fac­tory as typed fac­to­ries, so that para­graph applies to them. I prob­a­bly 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.

  • http://blog.ploeh.dk/ Mark See­mann

    Yes, makes sense. Good thing with the update :)

    I was just envi­sion­ing hordes of Morts going "but Krzysztof said we should never invoke Release!"… but then again, Morts are not par­tic­u­larly likely to use Wind­sor :)

  • John Simons

    I know you going to scream at me and tell me to go away!
    But why not for tran­sients let the GC do it's job?
    We all know that we need yo explic­itly call Release on tran­sients and half of the time we for­get, so why have this bur­den on the users?
    What is the ben­e­fit for the user?

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    John,

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

  • John Simons

    Yes I did, and I do under­stand the sce­nario you talk about.
    But there are also the sce­nar­ios that Mark refers too, where you have to explic­itly resolve/release a com­po­nent.
    It's the later sce­nario that I am more inter­ested in.

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    @John

    I would be inter­ested in a con­crete exam­ple. I can't really think of an exam­ple where typed fac­tory or proper lay­er­ing wouldn't be sufficient.

  • John Simons

    Ok you got me there :)
    Yes the type fac­tory would most def­i­nitely solve the exam­ples I have.

    But if that is the case, why have resolve/release APIs?
    And I think my orig­i­nal ques­tion is still valid, what is Wind­sor doing with the explicit ref­er­ence to my tran­sients, spe­cially tran­sients that do not have any depen­den­cies?
    Doesn't it just store all of them in a List in the Bur­den implementation.

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    @John — you need Release and Resolve for the few cases I out­lined in the post :)

    Like I said in the pre­vi­ous post Wind­sor tracks com­po­nents so that it can release them.

    "Wind­sor by default will track objects that them­selves have any decom­mis­sion con­cerns, are pooled, or any of their depen­den­cies is tracked."

    That means that tran­sients that don't have decom­mis­sion con­cerns and none of their depen­den­cies has any either, won't be tracked.

  • John Simons

    "That means that tran­sients that don't have decom­mis­sion con­cerns and none of their depen­den­cies 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

    Actu­ally what do you mean "decom­mis­sion con­cerns"?
    My tran­sient imple­ments IDis­pos­able, is that a "decom­mis­sion concerns"

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

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

    I'm not sure if v2.1.1 tracks all com­po­nents, I sup­pose the behav­ior hasn't changed much between last two versions.

    Yes — Dis­posal is a decom­mis­sion con­cern, Wind­sor will track the com­po­nent so that it can dis­pose of it.

  • http://blog.ploeh.dk/ Mark See­mann

    @John, in my opin­ion dis­pos­able com­po­nents are the main rea­son why this rule should exist for all con­tain­ers — not just Windsor.

    It would be a Leaky Abstrac­tion if an inter­face itself imple­mented IDis­pos­able (although I'm aware that cer­tain BCL inter­faces do just that), so con­sumers don't know whether the tran­sient IFoo they received imple­ments IDis­pos­able or not. They also don't know whether it's tran­sient or some­thing else, so they can't dis­pose of it either — even if they decided to break the LSP and explic­itly check for that.

    In other words, only the con­tainer can tell you whether the IFoo instance should be dis­posed or not. True to the Hol­ly­wood Prin­ci­ple, we don't query the con­tainer to fig­ure out whether the instance should be dis­posed or not — we just tell it that it we are done with it.

  • http://igorbrejc.net/ Igor Brejc

    Krzysztof, what about this scenario:

    inter­face ISer­vice : IDis­pos­able
    {

    }

    inter­face ISer­vice­Fac­tory
    {
    ISer­vice Cre­ate­Ser­vice();
    void Destroy (ISer­vice ser­vice);
    }

    and the code:

    using (ISer­vice ser­vice = serviceFactory.CreateService())
    {

    }

    If I under­stand your post cor­rectly, 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 prob­lem­atic, since it would imply I have to use try finally block in order to be sure the Destroy is really called, even in excep­tional cases.

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    Igor, this is a gray area.

    That's one of the cases that Mark men­tioned in one of ear­lier com­ments — in prin­ci­ple you don't own the object, the fac­tory owns it, and the inter­face should not expose IDis­pos­able at all.

    On the other hand prag­matic ben­e­fit of using state­ment has some advan­tages in cases like this.

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

  • http://igorbrejc.net/ Igor Brejc

    Krzysztof,

    I don't think the fact a com­po­nent is avail­able through some Wind­sor fac­tory should influ­ence its design, since the com­po­nent could be used else­where with­out IoC (cre­at­ing it with "new") and you still want it to clean up after itself.

    An idea: what if the typed fac­tory returned a proxy of a com­po­nent which would imple­ment "factory.Destroy()" in the Dis­pose method? Then you'd still be able to wrap it in the "using" block. Could this be done using the DynamicProxy?

  • http://kozmic.pl/Default.aspx Krzysztof Koźmic

    Igor, see the links I enclosed in pre­vi­ous comment.

    I'm not sure about the first para­graph of your last com­ment. What do you mean that "the fact a com­po­nent is avail­able through some Wind­sor fac­tory should influ­ence its design". I'm not propos­ing it should. Quite the con­trary — using the design I out­lined with­out the con­tainer would work with­out issues. Or am I miss­ing your point?

  • http://igorbrejc.net/ Igor Brejc

    Krzysztof,

    My state­ment was a com­ment on your state­ment: "in prin­ci­ple you don't own the object, the fac­tory owns it, and the inter­face should not expose IDis­pos­able at all". What I meant was that my inter­face (let's say IWe­b­Client) is a general-purpose com­po­nent which can be used with or with­out Wind­sor Cas­tle, so I need it to be IDis­pos­able. I don't want the fact that some day I'm going to cre­ate it through a DI con­tainer influ­ence all the other code which uses IWe­b­Client with­out any con­tain­ers (which would hap­pen if I made it non-disposable).

    OK, I've re-read you posts but I still don't have the com­plete pic­ture. If I under­stand cor­rectly, there's an inter­cep­tor that catches Dis­pose() meth­ods and releases the com­po­nent from the container.

    But what hap­pens with IDis­pos­able com­po­nents cre­ated through typed fac­to­ries? Does the typed fac­tory facil­ity auto­mat­i­cally cre­ate inter­cep­tors for such com­po­nents and then release them when the Dis­pose() method is called on a com­po­nent? Or do I have to add inter­cep­tors myself? You posts seem to imply the code is just a brain­storm­ing idea, so I don't know whether this was later included in the actual Wind­sor release.

  • http://blog.ploeh.dk/ Mark See­mann

    I think Nicholas Blumhardt said it best:

    "[An] inter­face […] gen­er­ally shouldn't be dis­pos­able. There's no way for the one defin­ing an inter­face to fore­see all pos­si­ble imple­men­ta­tions of it — you can always come up with a dis­pos­able imple­men­ta­tion of prac­ti­cally any interface."

    That applies whether or not you resolve that depen­dency via a con­tainer or wire it up man­u­ally. That's why we con­sider IDis­pos­able inter­faces Leaky Abstrac­tions. On the other hand, an imple­men­ta­tion can also imple­ment IDis­pos­able. There's noth­ing wrong with that.

    How­ever, it's a tricky sub­ject that I use more than ten pages on in my upcom­ing book, so it's hard to pro­vide full guid­ance in the con­text of these comments.

  • http://igorbrejc.net/ Igor Brejc

    @Mark,

    If you stick to Nicholas' phi­los­o­phy in a DI envi­ron­ment, then you will prac­ti­cally be unable to use the "using" block in your code, since none of the inter­faces you'll be using will be dis­pos­able. 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 imple­men­ta­tion imple­ments IDis­pos­able help you in the sit­u­a­tion where you only work through inter­faces and not con­crete implementations?

    Yes, you can stick IDis­pos­able to prac­ti­cally and inter­face. But my sug­ges­tion is to use a com­mon sense: if your inter­face rep­re­sents some kind of a sys­tem resource, it's a good guess it would be wise to pro­vide a mech­a­nism for dis­pos­ing it. Think files, graph­ics objects, HTTP con­nec­tions etc (I'm talk­ing about non-shared resources here, which you would typ­i­cally define as tran­sient in Wind­sor). If, on the other hand, it rep­re­sents some abstract ser­vice, you don't stick IDis­pos­able on it.

    It's a tricky sub­ject, but I doubt there's a one-liner solu­tion for it like Nicholas suggests.