(ASP).NET Core Dependecy Injection – Disposing

After several years of using the same Dependency Injection (DI) framework like Autofac you may have a good understanding how your components, implementing the interface IDisposable, are going to be disposed.

In this article:

pg
Pawel Gerr is architect consultant at Thinktecture. He focuses on backends with .NET Core and knows Entity Framework inside out.

With the nuget package Microsoft.Extensions.DependencyInjection the new .NET Core framework brings its own DI framework. It is not that powerful as the others but it is sufficient for simple constructor injection. Nonetheless, even if you don’t need some advanced features you have to be aware of how the components are destroyed by this framework.

Let’s look at a concrete example. Given are 2 classes, a ParentClass and a ChildClass:

				
					public class ParentClass : IDisposable
{
	public ParentClass(ChildClass child)
	{
		Console.WriteLine("Parent created.");
	}

	public void Dispose()
	{
		Console.WriteLine("Parent disposed.");
	}
}

public class ChildClass : IDisposable
{
	public ChildClass()
	{
		Console.WriteLine("Child created");
	}

	public void Dispose()
	{
		Console.WriteLine("Child disposed.");
	}
}
				
			

At first we are using Autofac to resolve ParentClass:

				
					var builder = new ContainerBuilder();
builder.RegisterType<ParentClass>().AsSelf();
builder.RegisterType<ChildClass>().AsSelf();
var container = builder.Build();

Console.WriteLine("== Autofac ==");
var parent = container.Resolve<ParentClass>();

container.Dispose();

				
			

With Autofac we are getting the following output:

				
					== Autofac ==
Child created
Parent created.
Parent disposed.
Child disposed.
				
			

And now we are using .NET Core DI:

				
					var services = new ServiceCollection();
services.AddTransient<ParentClass>();
services.AddTransient<ChildClass>();
var provider = services.BuildServiceProvider();

Console.WriteLine("== .NET Core ==");
var parent = provider.GetRequiredService<ParentClass>();

((IDisposable) provider).Dispose();
				
			

The output we get is:

				
					== .NET Core ==
Child created
Parent created.
Child disposed.
Parent disposed.
				
			

Comparing the outputs we see that Autofac destroys the outer compontent (i.e. ParentClass) first and then the inner component (i.e. ChildClass). The .NET Core DI does not honor the dependency hierarchy and destroys the components in the same order they are created.

Most of the time the behavior of .NET Core DI is not a problem because the components just free internal resources and are done. But in some cases the outer component has to do something like to unregister from the inner component that may live on. If the inner component is/will not be disposed then all works fine; if not then we get ObjectDisposedException.

If you start a new project with .NET Core I suggest to stay with DI framework you are familiar with unless it is a sample application.

PS: Further information of how to switch from .NET Core DI to other frameworks in an ASP.NET Core application: Replacing the default services container  and ASP.NET Core with Autofac

Free
Newsletter

Current articles, screencasts and interviews by our experts

Don’t miss any content on Angular, .NET Core, Blazor, Azure, and Kubernetes and sign up for our free monthly dev newsletter.

EN Newsletter Anmeldung (#7)
Related Articles
.NET
KP-round
.NET 8 brings Native AOT to ASP.NET Core, but many frameworks and libraries rely on unbound reflection internally and thus cannot support this scenario yet. This is true for ORMs, too: EF Core and Dapper will only bring full support for Native AOT in later releases. In this post, we will implement a database access layer with Sessions using the Humble Object pattern to get a similar developer experience. We will use Npgsql as a plain ADO.NET provider targeting PostgreSQL.
15.11.2023
.NET
KP-round
Originally introduced in .NET 7, Native AOT can be used with ASP.NET Core in the upcoming .NET 8 release. In this post, we look at the benefits and drawbacks from a general perspective and perform measurements to quantify the improvements on different platforms.
02.11.2023
.NET
KP-round
.NET 8 introduces a new Garbage Collector feature called DATAS for Server GC mode - let's make some benchmarks and check how it fits into the big picture.
09.10.2023