I am using a Castle Windsor Typed Factory. In our registration code it is set up so it can create a Transient component:
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IThingFactory>().AsFactory());
container.Register(Component.For<IThing>().ImplementedBy<TransientObject>().Named("TransientObject").LifeStyle.Transient);
From my understanding of the Castle Windsor Typed Factory documentation I thought that a Transient object must be released by a Typed Factory method, otherwise the Typed Factory would keep a reference to the object. I tried to prove this by writing a test that used the method explained in this StackOverflow article.
But to my surprise it doesn't actually fail, implying that although I have not released the transient object back to the factory, it can still be reclaimed by the GC. I'm concerned that perhaps my test is misleading and there really is a leak.
So my question is: is my test wrong, or is the documentation wrong?
Here's the test:
var factory = container.Resolve<IThingFactory>();
WeakReference reference = null;
new Action(() =>
{
var service = factory.GetTransientObject();
reference = new WeakReference(service, true);
})();
GC.Collect();
GC.WaitForPendingFinalizers();
Assert.That(reference.Target, Is.Null, "reference should be null");
Windsor tracks Transient
instances only if they have some decommission concerns. A typical example of a decommission concern is that a class implements IDisposable
interface.
So, if the IThing
is Transient
and it does not implement IDisposable
and it does not have any other decommission concerns then Windsor will NOT track it and garbage collector can/will remove instances of IThing
.
BUT (and this is a big but), I suggest you do not ever rely on this behavior. IThing
may be changed by a developer and it may become disposable in the future. Or it may get another decommission concern. And suddenly a memory leak occurs. Therefore a simple rule should be followed:
Any time an object is resolved explicitly by calling container.Resolve
it has to be released by calling container.Release
. Also any time an object is created explicitly by a typed factory, it has to be destroyed explicitly by the typed factory. Does not matter if the object is transient or not, take care of its lifetime. Always. Creator of an object (be it windsor or typed factory) is responsible for destroying of the object.
Basically, @piotrwest was right in his comment. However, this answer aims to explain that it is not only about IDisposable
- it is about decommission concerns (IDisposable
is simply one of them).
This great article explains more details.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With