# Dependency Injection Conventions with ASP.NET Core 1.1 and Autofac

With the 1.1 release of ASP.NET Core, it has now become a little easier to configure 3rd party dependency injection containers into your application. `Autofac.Extensions.DependencyInjection` 4.1.0 was recently released with support for this new feature, so I figured I'd try it out.

##### DI Conventions

Ever since ASP.NET MVC was introduced, we've been accustomed to relying on conventions that make the development experience with the framework a little nicer. In ASP.NET Core, probably one of the best examples of this is the `Startup` class. This is a simple .NET class that we use to compose the various features of our application. A fairly barebones app only requires that you to create a `Configure` method that accepts an instance of `IApplicationBuilder`. Then by convention, the framework will discover this method and configure your application. For richer applications that require additional services and wish to leverage the built in dependency injection features, a `ConfigureServices` can be added to the `Startup` class which will accept an instance of `IServiceCollection` that you can use to wire up your services.

      public void ConfigureServices(IServiceCollection services)
      {
        services. AddTransient<IDataService, MyDataService>();
      }
    

Some of us might have existing investments in a particular DI framework that we'd like to integrate into the ASP.NET Core DI infrastructure. To do that, we'd need an implementation of `IServiceProvider` that would adapt your framework of choice. For example, if you use `Autofac` then the `Configure` method might look something like this.

      public IServiceProvider ConfigureServices(IServiceCollection services)
      {
        services.AddMvc();
    
        // Create the container builder.
        var builder = new ContainerBuilder();   
        builder.RegisterType<MyDataService>().As<IDataService>();
        builder.Populate(services);
        var container = builder.Build();
    
        // Create the IServiceProvider based on the container.
        return new AutofacServiceProvider(container);
      }
    

Just like the `Configure` method, the framework will discover the implementation of `ConfigureServices` in the `Startup` class and run it for you.

##### Introducing ConfigureContainer

Starting with ASP.NET Core 1.1, 3rd party DI frameworks are able plug in earlier in the pipeline which has the added benefit of reducing the amount of code needed to use them. At the core of this is the [IServiceProviderFactory](https://github.com/aspnet/DependencyInjection/blob/rel/1.1.0/src/Microsoft.Extensions.DependencyInjection.Abstractions/IServiceProviderFactory.cs?ref=cecilphillip.com) interface. Frameworks like `Autofac` can implement this interface ([see here](https://github.com/autofac/Autofac.Extensions.DependencyInjection/blob/v4.1.0/src/Autofac.Extensions.DependencyInjection/AutofacServiceProviderFactory.cs?ref=cecilphillip.com)). Then it can be registered when `WebHostBuilder` is getting setup. ASP.NET Core can now use this factory to replace its default service provider that gets created at startup. Let's see how we can update the example above to make use of this new feature.

First, make sure you have at least version 4.1.0 of `Autofac.Extensions.DependencyInjection` installed in your application. Next, we'll remove that `Autofac` setup code from `ConfigureServices` and add a new method to the `Startup` class, `ConfigureContainer`.

    public void ConfigureContainer(ContainerBuilder builder) {
        builder.RegisterType<FakeDataService>().As<IDataService>();
    }
    
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddMvc();
    }
    

Just like `Configure` and `ConfigureServices`, `ConfigureContainer` will get discovered and executed by convention when your application starts. You can also create variations based on the the hosting environment. So for example, you can have **ConfigureDevelopmentContainer**, **ConfigureStagingContainer** and so on.

The parameter to the `ConfigureContainer` method will be the type that you use to compose your DI container. In the case of `Autofac`, this happens with the `ContainerBuilder` class. Now any of the registration code for your 3rd party DI framework can now be placed inside of the `ConfigureContainer` method.

The last thing that needs to happen is for us to register the `IServiceProviderFactory` implementation. `Autofac` provides the [AddAutofac](https://github.com/autofac/Autofac.Extensions.DependencyInjection/blob/v4.1.0/src/Autofac.Extensions.DependencyInjection/ServiceCollectionExtensions.cs?ref=cecilphillip.com) extension method that helps out with that. Using the `ConfigureServices` method off of `IWebHostBuilder`, we can update the hosting bootstrap code to plug in `Autofac`.

    public static void Main(string[] args)
    {
        var host = new WebHostBuilder()
            .UseKestrel()
            .ConfigureServices(services => services.AddAutofac())
            .UseContentRoot(Directory.GetCurrentDirectory())
            .UseIISIntegration()
            .UseStartup<Startup>()
            .Build();
        host.Run();
    }
    

Now a new `IServiceProviderFactory` is configured in the application and we can continue registering additional services with `Autofac`.

One mistake I made when I was first trying this out was I tried to call the `AddAutofac` extension method inside the `ConfigureServices` of the `Startup` class. This doesn't work because it's too late in the initialization of your application to register a custom `IServiceProviderFactory`. It should be called before any of the `Startup` methods get called. In this instance, we'll have to use the `ConfigureServices` method of `IWebHostBuilder` instead.

##### Conclusion

Overall I think this new approach to 3rd party DI integration is much nicer for the application developer.

I actually thought the way this feature was introduced was pretty interesting, so I went digging through the code in GitHub. If you'd like to see where some of this black magic happens, take a look at the [StartupLoader](https://github.com/aspnet/Hosting/blob/rel/1.1.0/src/Microsoft.AspNetCore.Hosting/Internal/StartupLoader.cs?ref=cecilphillip.com) class in the Hosting repo.
