Windsor: Typed factory should not track or dispose the objects it creates

If an object is created by Castle Windsor calling the typed factory’s resolve/create method, then I agree that Castle Windsor should be the one to release/dispose.

If an object is created by me calling the typed factory’s resolve/create method, then I should be the one to release/dispose.

In other words, the returned object’s lifespan should not be tied to the factory but to whatever caused the call to the factory. That could be me manually (in which case I manually manage the lifespan), or it could be Castle Windsor resolving a component (in which case the lifespan should be tied to the component that needs the object, not to the factory itself). In neither case should the typed factory itself be tracking the objects it creates.

If I use a factory to construct an IDisposable, I am the one responsible to put it in a using statement (if it’s a local) or call Dispose (if it’s a field). It’s the expected pattern in .NET with any IDisposable-returning creation method.

In my case, that is kind of the whole point of injecting a Func<DbContext>- so that I have absolute control of creation and disposal of every DbContext. I need that control.

The only reason I’m not newing up the DbContext myself in the using block is that the DbContext has a dependency, but I need the same semantics:

using (var db = new MyDbContext(thingsToInject))
{
    var query1 = await db.Thing1();
    var query2 = await db.Thing2();
    ...
    await db.Command();
}

Should have the same disposal semantics, but doesn’t:

using (var db = dbContextFactory.Invoke()) // Use Castle Windsor to handle DI
{
    var query1 = await db.Thing1();
    // Problem happens when Castle Windsor (rightfully) disposes dbContextFactory because the viewmodel is closed
    // db gets disposed too early! I need it to last until the end of the using block! (duh?)
    var query2 = await db.Thing2();
    ...
    await db.Command();
}

I need at least an option to disable tracking objects instantiated by me from typed factories, but I also think it’s a more preferable idiom to not track them and that tracking object returned from manual calls should be disabled completely or at least disabled by default.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 15 (14 by maintainers)

Most upvoted comments

I don’t think that Func<T> forces the container to do anything. What I do think is that semantically, Func<T> represents the ability to obtain multiple Ts and also control when in time the Ts are created. If Func<T> is not used for multiple instances or for controlling the lifestyle, you should just use T because it is semantically more appropriate.

In particular your DbContext has some dependencies that container satisfies. As calling Dispose on DbContext does not notify Windsor - these dependencies are now flying somewhere in the memory.

Now that is a very good point which I didn’t catch earlier, which does seriously challenge my position. You are right about this. What an oversight. I actually do need to release DbContexts, so I’m forced to use interface factories or wait for the delegate factory to be disposed and hope that isn’t too long.