Using transient factories in Castle Windsor - c#

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?

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

So the deeper question is related to IDisposable. Why are you using it? Are you really keeping track of unmanaged/limited resources? Are you using it to really dispose something or as a shutdown protocol?
All these will go away if you change Windsor's release policy -- thus making you take care of when/if [to] call dispose. The container is trying to help you by keeping track of what and when to dispose things, but it can only do so much, so sometimes it's better to step up and take over the responsibility.
Another option is to turn off the tracking and expose a service that keeps track of things to dispose. This can be more semantical and understand your business/infrastructure needs.
In sum: what you're doing is fine, but it's not all that common to instantiate a transient factory every time you need the factory to create something. Make sure you document this for the your own future self.

Related

Should a static class dispose of its IDisposable variables in a "static destructor"?

If a static class has any IDisposable static variables, should that class have a "static destructor" to dispose of them? For example:
public static StaticClass
{
static SomeDisposableType
someDisposable = new SomeDisposableType();
static readonly StaticDestructor
staticDestructor = new StaticDestructor();
private sealed class StaticDestructor
{
~StaticDestructor()
{
someDisposable.Dispose();
}
}
}
No, it should not.
There's no way for the runtime to know when your static class will be used for the last time. There's no way it can know to invoke cleanup early.
Therefore, the only "sensible" time to perform cleanup would be when the entire process is about to terminate. But that's not the right time to be cleaning up either. For a similar, unmanaged, take on this, read Raymond Chen's When DLL_PROCESS_DETACH tells you that the process is exiting, your best bet is just to return without doing anything:
The building is being demolished. Don’t bother sweeping the floor and emptying the trash cans and erasing the whiteboards.
Now, some may bring up the argument that some of your disposables may represent external resources that will not be cleaned up/released when the OS destroys your process. Whilst that's true, those external resources have to cope with e.g. your process being terminated by the user or (if not co-located on the same machine) a power supply failure taking the entire machine away. You don't get to run any cleanup code when there's a power cut. So they already have to be coded to deal with your process not being able to release the resources.
There are some code smells happening here.
StaticClass is tightly coupled to the specific types that it depends upon, rather than just their interfaces.
StaticClass determines the lifetime of the services that it uses.
This is preventing StaticClass from being thoroughly unit-testable. For example, you cannot test the behavior of StaticClass without also testing the behavior of SomeDisposableType.
I'd almost always recommend making your StaticClass non-static, and using constructor injection to inject the services it depends on as interfaces, allowing a Dependency Injection framework's configuration to determine the lifetime of those objects.
If there's no compelling reason to have StaticClass be a singleton, then just let it be transient. Your DI framework should take care of cleaning up the disposable that gets injected into it.
If there is a compelling reason to have StaticClass be a singleton, think really hard about your separation of concerns: is StaticClass doing too much? For example, maybe it's doing some work to find values, and then storing those values to avoid doing that work again later. Or perhaps it's saving the state of certain properties of your application, and acting based on that state. In these cases, you can usually separate the state-saving or memoizing/caching work in a separate class that can be singleton-bound. Then your service that consumes this state or cached values can still be transient, and its disposable dependencies can still be disposed after it's done a specific job.
If, after considering all of the above, you're still convinced this class needs to have a long lifetime, you should carefully consider the lifetime of your disposable dependency. Usually if a class is disposable, that's because it holds on to resources that should be released from time to time. In that case, rather than injecting that class directly, perhaps you should inject a factory which you can use to construct the service on-demand and then dispose it as soon as an action is complete via a using statement.
It's hard to make more specific recommendations without knowing more about your specific classes, but these are the patterns I've found to work best in the vast majority of cases.

Which dependency injection lifetime should be preferred?

For a REST api, that has no dependencies between requests and is using ASP.NET Core DI.
I have heard conflicting arguments when choosing the most appropriate:
Prefer transient and then scoped and avoid singleton due to memory and multi-threading issues and also because singletons should not be injected with other lifetimes due to captive dependencies
Prefer singletons to save time instantiating objects and prevent opening multiple connections
I understand they work differently but is there a 'go-to' lifetime? Should it start with 'transient' and move to others as required?
Are there any investigations proving the instantiation time saved by singleton is actually relevant?
I'm not going to say there's a right or wrong way here, but I'll share my personal experience.
I've tried both ways, and ended up finding that it's best to start with transient and then expand the scope as necessary.
Think in terms of the Single Responsibility Principle and Reasons for Change. The reason that your service's lifetime scope may need to change will likely be linked to a change you make to the service implementation itself. When that Reason happens, you want to only need to change a single class.
If you have a service that needs to be longer-lived than most of your other services, all you have to do is make it longer-lived and inject factories for any shorter-lived dependencies into it.
On the other hand, if you have a class that needs to be shorter-lived than most of your other services, you'll end up having to inject it as a factory into all the longer-lived services. So one Reason for Change impacts code all over your code base.
Of course, this is assuming you're doing things correctly: avoiding captive dependencies and remembering to make non-thread-safe services transient. I find it's far easier to remember which services need to be long-lived and override the defaults in that direction, than it is to remember which services shouldn't be long-lived and override the defaults that way. And I've found that failure to do the latter leads to much more insidious bugs that are harder to notice and result in greater damage.
With regards to performance: I haven't done performance testing with the ASP.NET Core built-in DI framework, but I've found that SimpleInjector is fast enough that the time and memory overhead of creating new instances of services is trivial in comparison with the other work my app does (like querying databases).
With regards to preventing opening multiple connections: SQL Server connections are pooled automatically so the cost to creating a new SqlConnection() and disposing it several times in a request is generally pretty trivial.
Should it start with 'transient' and move to others as required?
Yep. Transient services are simpler to implement correctly, and simply instantiating an object every time a dependency is resolved would normally not cause a significant performance problem.

Castle Windsor Typed Factory without release does not leak

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.

What is the lifetime of a transient dependency resolved via .UsingFactoryMethod but not explicitly resolved using the kernel?

I have the following class which exposes a public factory method instead of a public constructor:
public class SomeDependency
{
private readonly string _someValue;
private SomeDependency(string someValue)
{
_someValue = someValue;
}
public static SomeDependency CreateSomeDependency(string someValue)
{
return new SomeDependency(someValue);
}
}
I configure it in the container to have a transient lifestyle and to be created via the static method:
Container.Register(Component.For<SomeDependency>()
.UsingFactoryMethod(k => SomeDependency.CreateSomeDependency("a value"))
.LifestyleTransient());
All components that this dependency is injected into are configured to be transient as well.
Will the container dispose this dependency when objects that depend on it fall out of scope or will this dependency fail to be disposed and make everything stick around?
It will be disposed if:
It implements IDisposable, which it currently does not, and
The composition root calls Container.Release() for the component that caused SomeDependency to be instantiated.
You cannot simply rely on the component going out of scope for disposal to be triggered.
If you are referring to garbage collection rather than disposal, then your current implementation may work ok with the object becoming available for GC when it goes out of scope. In most cases, transient components that do not implement IDisposable will not be tracked by the container but it can depend on what other facilities you are using in your container. Therefore, it is always best to ensure Release is called.
Is the concern on the static method? If so, that should not cause an issue with marking an unused object for disposal. I am not sure I would use the pattern, but I don't see the entire motivation for the pattern in your post, so I can't judge.
If this were a Singleton (static variable served through a static method), you would not dispose, but that would be the intent of the pattern.
If you are seeing memory usage grow and worried about a memory leak, and thus asking the question, you can dig deeper, but it is more likely you are just seeing how .NET operates. Disposal happens as memory is needed, so it is normal to see .NET appearing to hold onto memory as if it was a memory leak. In almost every case I have investigated for clients who thought they had memory leaks, it was simply .NET not disposing of objects until memory was needed (default behavior).
If you are seeing a potential problem, there are ways to probe memory leaks in .NET. I would recommend using a tool rather than digging through dumpheap, but the pricing for certain tools may be prohibitive in some cases. You can use trials of various products if you simply need the peace of mind that you have not caused a memory leak.

WSTrustChannelFactory as a singleton. Is it the best practice?

I'm working with an application that uses WSTrustChannelFactory to create trust channels, I noticed that the code is creating a new WSTrustChannelFactory everytime a new channel is needed.
I've never worked with this before but since this is a factory I suppose it can be implemented as a singleton.
Am I right? If so, is there any additional consideration to take (will the factory always be "usable" or there are any scenarios/exceptions where it should be replaced with a new instance)?. Also, is the factory creation an expensive operation, such as a WCF ChannelFactory creation?
Am I right?
Yes, I think you are. I've worked on several projects where we used a channel factory and each time it was a singleton. It certainly has its limits and can become a bottleneck under a very high load, but for a lot implementations I think you are fine.

Categories

Resources