Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When are .NET Core dependency injected instances disposed?

ASP.NET Core uses extension methods on IServiceCollection to set up dependency injection, then when a type is needed it uses the appropriate method to create a new instance:

  • AddTransient<T> - adds a type that is created again each time it's requested.
  • AddScoped<T> - adds a type that is kept for the scope of the request.
  • AddSingleton<T> - adds a type when it's first requested and keeps hold of it.

I have types that implement IDisposable and that will cause problems if they aren't disposed - in each of those patterns when is Dispose actually called?

Is there anything I need to add (such as exception handling) to ensure that the instance is always disposed?

like image 553
Keith Avatar asked Nov 28 '16 12:11

Keith


People also ask

Does dependency injection dispose?

DependencyInjection disposes registered services automatically. It's just the question when the dispose takes place. Automatic dispose of transient and scoped services happen at the end of a scope. With ASP.NET Core applications, scopes are created with every HTTP request – after the request, services are disposed.

How does dependency injection work .NET Core?

Dependency Injection is the design pattern that helps us to create an application which loosely coupled. This means that objects should only have those dependencies that are required to complete tasks.

Do transient services get disposed?

Disposable transient services are captured by the container for disposal. This can turn into a memory leak if resolved from the top-level container. Enable scope validation to make sure the app doesn't have singletons that capture scoped services.

How can dependency injection be resolved?

Resolve dependencies using IServiceProvider You can use the IServiceCollection interface to create a dependency injection container. Once the container has been created, the IServiceCollection instance is composed into an IServiceProvider instance. You can use this instance to resolve services.


1 Answers

The resolved objects have the same life-time/dispose cycle as their container, that's unless you manually dispose the transient services in code using using statement or .Dispose() method.

In ASP.NET Core you get a scoped container that's instantiated per request and gets disposed at the end of the request. At this time, scoped and transient dependencies that were created by this container will get disposed too (that's if they implement IDisposable interface), which you can also see on the source code here.

public void Dispose() {     lock (ResolvedServices)     {         if (_disposeCalled)         {             return;         }         _disposeCalled = true;         if (_transientDisposables != null)         {             foreach (var disposable in _transientDisposables)             {                 disposable.Dispose();             }              _transientDisposables.Clear();         }          // PERF: We've enumerating the dictionary so that we don't allocate to enumerate.         // .Values allocates a ValueCollection on the heap, enumerating the dictionary allocates         // a struct enumerator         foreach (var entry in ResolvedServices)         {             (entry.Value as IDisposable)?.Dispose();         }          ResolvedServices.Clear();     } } 

Singletons get disposed when the parent container gets disposed, usually means when the application shuts down.

TL;DR: As long as you don't instantiate scoped/transient services during application startup (using app.ApplicationServices.GetService<T>()) and your services correctly implement Disposable interface (like pointed in MSDN) there is nothing you need to take care of.

The parent container is unavailable outside of Configure(IApplicationBuilder app) method unless you do some funky things to make it accessible outside (which you shouldn't anyways).

Of course, its encouraged to free up transient services as soon as possible, especially if they consume much resources.

like image 56
Tseng Avatar answered Oct 12 '22 22:10

Tseng