Search code examples
c#inversion-of-controlcastle-windsorcastle-windsor-3

Transient component using a PerWebRequest component, when does the PerWebRequest component go out of scope?


I'm trying to make sense of a somewhat complicated scenario. Basically if I have class X that is registered in Castle as LifestyleTransient():

Component.For<IX>()
.ImplementedBy<X>()
.LifestyleTransient()

X looks something like:

public X : IX
{
    private IY _y;
    public X(IY y)
    {
        _y = y;
    }
    ....
}

and Y is registered thus:

Component.For<IY>()
.ImplementedBy<Y>()
.LifestylePerWebRequest()

and looks like:

public Y : IY, IDisposable
{
    private Object obj;
    public Y()
    {
       obj = new Object();
    }  

   public void Dispose()
   {
      obj.Dispose();
   }
}

If I create an instance of X and Release it:

WindsorContainer Container;
IX x = Container.Resolve<IX>();
Container.Release(x);

when does Dispose get called on Y? Is it at the end of the web request or when the instance of x is released? Does Dispose get called at all?!


Note: This is a somewhat converluted example, my actual example is much more complicated and invloves an MVC ControllerFactory and various other pieces of technology, but the question pretty boils down to the above in it's simpliest form.


Solution

  • With a bit of experimentation is appears the following is true:

    • Dispose() will get called
    • Dispose is called at the end of the web request
    • If multiple transient Xs are created and released Dispose is only called (on Y) once at the end of the web request. Not when the transient container objects are released

    Caveats

    I've came to this conclusion by debugging the Dispose method, etc. I'm presuming me debugging this hasn't made any affect on how this performs. I haven't found any conclusive documentation on how this is supposed to work and would welcome anyone that does find this?

    My implementation was slightly different to that in the question, I guessed that Windsor would need to know if the interface was IDispoable or not, so IY looks like:

    interface IY : IDisposable
    

    I haven't tested if this is relevant (if it aint broke, don't fix it).