Castle Windsor Typed Factory without release does not leak
Asked Answered
H

1

7

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");
Hackler answered 28/10, 2016 at 15:2 Comment(3)
what's the question?Bufordbug
Does your "IThing" extend/implement IDisposable interface? It's written that "Windsor always tracks disposable non-singleton components resolved via typed factory.".Whitted
I think piotrwest has answered my question: no, my IThing does not implement IDisposable. I'd missed the implications of "Windsor always tracks disposable...". Thanks!Hackler
A
9

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.

Ardel answered 7/4, 2017 at 7:5 Comment(1)
Great explanation!Highbrow

© 2022 - 2024 — McMap. All rights reserved.