Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Prevent Autofac from holding disposable instances

I had a problem with Autofac creating memory leaks. After some investigation I came to conclusion that the memory leaks is result of Autofac holding disposable instances. So there are two ways to resolve this situation: 1. Dispose of scope 2. Use Owned<>/ExternalyOwned() syntax when resolving/registering .

The problem with the first that we do not use (besides very specific small sub cases) scopes at all, all the registration and resolving are done within single "global" scope, which never disposed. We do not want to use locator anti pattern, so basically we have one top level "resolve" and that's it, so scopes are not an option there.

The problem with second (which is I selected as temporal solution for now) is that we want our code to be as generic IOC as possible, not tied to Autofac, so having Owned in constructors is not an option (after all one of the main reasons we use Autofac is not just IOC but ability to unit test classes without Autofac, by FakeItEasy or Mock) , this force as to put .ExternallyOwned() on every registration of disposable class that can be created as transient (.InstancePerDependency() or default). Since this become really hard to track and classes and their usages can change, this basically means I put .ExternallyOwned() on every registration, which is ok, but rather inconvenient.

So my question is - Is there any way to disable this feature globally (basically so each class registered, registered as with .ExternallyOwned() by default) ? Or maybe is there are another solution to this problem I did not considered ?

Thank you.

like image 767
TheLordkiron Avatar asked Dec 09 '25 12:12

TheLordkiron


1 Answers

Technically it isn't Autofac that is causing the memory leaks. It is the wrong usage of Autofac. Creating scopes and disposing them is the only real solution (even though that might be a lot of work).

If you want to use ExternallyOwned, you could consider making it a bit easier by creating an extension method that will do it for you. With a simple find+replace in all files you can use your new method.

public static IRegistrationBuilder<TImplementer, ConcreteReflectionActivatorData, SingleRegistrationStyle> 
    RegisterTypeAsExternallyOwned<TImplementer>(this ContainerBuilder builder)
{
    return builder.RegisterType<TImplementer>().ExternallyOwned();
}

I'm writing this in a browser, so I'm not entirely sure of how it will compile. But this is the only alternative I can come up with.

Be careful with ExternallyOwned. It will prevent Autofac holding reference to those objects, but it does mean that you have to dispose the instances yourself.

like image 84
Jeroen Avatar answered Dec 12 '25 00:12

Jeroen



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!