.NET Abstractions - It's not just about testing!
ASP.NET Core with IIS: Setup Issues

(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.

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

Comments

Feed You can follow this conversation by subscribing to the comment feed for this post.

Bjorn Coltof

Nice post! The examples for registration don't include the types being registered.

Pawel Gerr

@Bjorn Coltof: Thanks, they got eaten by the editor :)

Verify your Comment

Previewing your Comment

This is only a preview. Your comment has not yet been posted.

Working...
Your comment could not be posted. Error type:
Your comment has been posted. Post another comment

The letters and numbers you entered did not match the image. Please try again.

As a final step before posting your comment, enter the letters and numbers you see in the image below. This prevents automated programs from posting comments.

Having trouble reading this image? View an alternate.

Working...

Post a comment

Your Information

(Name and email address are required. Email address will not be displayed with the comment.)