question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Typed factory should not track or dispose the objects it creates

See original GitHub issue

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.

Issue Analytics

  • State:closed
  • Created 7 years ago
  • Comments:15 (14 by maintainers)

github_iconTop GitHub Comments

2reactions
jnm2commented, Jul 6, 2016

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.

0reactions
IanYatescommented, Jul 7, 2016

This seems pretty much concluded as a discussion, but it was a good read. I use interface-based typed factories for the very reason that was ultimately mentioned

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.

It also means that if my DbContext was a singleton instead of transient, it could potentially be kept around rather than new’d and disposed each time.

One other thing typed factories offer is the ability to accept parameters as part of the factory.create(..) method and have them flow through to the eventually created component. I don’t use it often but it’s been handy when required.

Lifetime then isn’t managed by IDisposable, but that’s OK because the factory interface is your code and it’s not hidden - it’s actually part of the contract to get a new widget constructed (Windor’s automatic implementation of the interface is what makes this all very elegant IMHO).

Read more comments on GitHub >

github_iconTop Results From Across the Web

Should factory keep track of created IDisposable objects?
So my primary answer to your question is, no, the factory should not keep track of created IDisposable objects. However, if your factory...
Read more >
Dependency injection guidelines - .NET
If a type or factory is registered as a singleton, the container disposes the singleton automatically.
Read more >
From Dispose Pattern to Auto-disposable Objects in .NET
This article will not deal with implementing the Dispose pattern. ... Why not accept a factory that will create the disposable object?
Read more >
HttpClient Creation and Disposal Internals ... - Steve Gordon
In this post I answer the question of whether we need to dispose of HttpClient instances and look at this in relation to...
Read more >
IDisposable Interface in C# | Using-Dispose Pattern
Instance methods other than Dispose() can throw an ObjectDisposedException when resources are already disposed.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found