Search code examples
c#castle-windsorfactorycastletransient

Using transient factories in Castle Windsor


If you use the TypedFactoryFacility in Windsor to generate factories for you based on an interface, the factory itself can be registered as Transient. It turns out that the factory will then release all transient objects that it created when the factory itself is disposed after release.

container.AddFacility<TypedFactoryFacility>();
container.Register(
    Types.FromThisAssembly().BasedOn<IFactory>().Configure(
        x => x.AsFactory()).LifestyleTransient());

This means that if I create the auto-generated factories as transient it neatly allows me to forget about Releaseing the object created from the factory (as long as I manage the lifetime of the factory itself, of course). The lifetime of such a transient factory would be tied to some other transient object, so when that object gets released, the factory is released, and everything that factory created.

Personally, I hate having to remember to explicitly Release() objects, and this cleans up the code a lot, so this makes me very happy. But the question is: Is this reasonable practice? It all just seems too easy.

Is there a downside to creating a new factory instance each time a factory is required?

Am I digging myself a terrible hole?


Solution

  • The automatic factory mechanism in Castle is based on Castle.DynamicProxy; I imagine that if you use the factory as a transient component you have to pay for the creation of the ProxyGenerator at each resolution, unless some other caching mechanism exists.

    The documentation warns against recreating the the ProxyGenerator each time:

    If you have a long running process (web site, windows service, etc.) and you have to create many dynamic proxies, you should make sure to reuse the same ProxyGenerator instance. If not, be aware that you will then bypass the caching mechanism. Side effects are high CPU usage and constant increase in memory consumption

    However it is entirely possible that there is some mechanism that prevents this problem in Windsor, or that the documentation is obsolete.

    My recommendation: test with a loop on your transient factory resolution, then resolve your component; keep an eye on memory (also loaded assemblies; maybe the proxied code is loaded in a side assembly) and processor usage to determine whether or not your trick is viable