loading...

Deep Dive - Autofac Integration in ASP.NET Core Dependency Injection

ggmueller profile image ggmueller ・3 min read

One thing that seemingly remains consistent, is that the integration of Autofac with ASP.NET keeps changing. Starting with ASP.NET Core 3.0 this changed, because the generic host was introduced.

I will quickly explore the usage of Autofac in ASP.NET and then dive a bit into the details of its core. Together with the implementation in ASP.NET Dependency Injection it is an interesting design, although not quite as obvious.

Installation and Usage

Installation is simple. Reference Autofac.Extensions.DependencyInjection in your ASP.NET application.

To use Autofac in your application, go to the class that creates our Host, typically this is your Program.cs and insert .UseServiceProviderFactory(new AutofacServiceProviderFactory()).

It could look like this:

public class Program
  {
    public static void Main(string[] args)
    {
      var host = Host.CreateDefaultBuilder(args)
        .UseServiceProviderFactory(new AutofacServiceProviderFactory())
        .ConfigureWebHostDefaults(webBuilder => webBuilder.UseStartup<Startup>())
        .Build();

      host.Run();
    }
  }

This enables Autofac as DI container in your ASP.NET Core Application.

Then you can add a ConfigureContainer method to your Startup class and configure the container using the ContainerBuilder you are used to as Autofac user.

public void ConfigureContainer(ContainerBuilder builder){
    builder.RegisterAssemblyModules(typeof(Startup).Assembly);
}

The integration also supports taking dependencies on registration in the IServiceCollection. So if you have on library that only supports registration with the ASP.NET Dependency Injection you do not have to worry. You can use it in your application.

These methods also support environment based naming conventions. I am not a fan of them but you can find the conventions in the Autofac docs.

What is registered?

The core of the integration is the AutofacServiceProviderFactory.

A ServiceProviderFactory is a abstraction within ASP.NET Dependency Injection. It allows Dependency Injection Frameworks to be used with ASP.NET, combining the advantage of having the an unified configuration for dependencies (useful for frameworks, so they only have to support one style of configuration), with the power of existing DI containers out there.

So it has two purposes.

First: It creates the DI container builder and populates it with dependencies from the ASP.NET ServiceCollection. The developer can then configure additional dependencies or replace the dependencies registered using the Autofac mechanisms.

Second: It builds the container and wraps it as ServiceProvider to be used in the framework.

Adding scopes

Working with DI containers and ASP.NET you will know that there are different scopes for objects and their dependencies.

The basic cases are Singleton and PerDependency, where Singleton is on object per application is instantiated and PerDependency creates an object for every dependency that requires the object.

In a HTTP framework you want to share some state application wide, but some dependencies should be once per request.

An example would be an UnitOfWork from an ORM. Once a dependency required it on the request, it should stay the same UnitOfWork for the whole request.

Therefore a LifetimeScope (in Autofac terminology) or ServiceScope (ASP.NET terminology) exists.

It is created when a new Request starts and is disposed when the request is completed.

ASP.NET needs a factory to create these ServiceScopes. When populating the ContainerBuilder Autofac adds this factory (AutofacServiceScopeFactory) to itself, so that ASP.NET can resolve it.

Its also interesting how this is integrated in ASP.NET. When the HttpContext of a Request is constructed it gets a reference to the ServiceScopeFactory.

The first time a service is resolved from the request it instantiates the ServiceScope, thus resolving all the dependencies configured for this scope.

Conclusion

The Autofac integration is implemented as it is expected from a DI container implementation for ASP.NET Core.

What is most interesting, is how the container registers its own implementations in itself, in order for ASP.NET to resolve it.

When debugging this a few months ago I missed this detail, thus suspecting an error of mine to be in the DI integration. Obviously I was wrong...

Posted on by:

ggmueller profile

ggmueller

@ggmueller

I am a Software Engineer loving to collaborate with Ops to tear down silos and improve software quality. Communication and collaboration are the skills I value most.

Discussion

pic
Editor guide