Close

January 11, 2019

Fixing My Legacy Application: Dependency Injection

Continuing my series on fixing my real-world legacy application, I will now introduce dependency injection.

First, I simply installed the Autofac.Mvc5Autofac.Mvc5.Owin and Autofac.WebApi2.Owin NuGet packages. This changes nothing of course.

So next, we tell ASP.NET to let Autofac handle the creation of the controllers. In our Startup class, we add:

var builder = new ContainerBuilder();
            builder.RegisterControllers(typeof(MvcApplication).Assembly);
var container = builder.Build();

DependencyResolver.SetResolver(new AutofacDependencyResolver(container));

app.UseAutofacMiddleware(container);
app.UseAutofacMvc();

// For WebAPI:
var config = GlobalConfiguration.Configuration;            config.DependencyResolver = new AutofacWebApiDependencyResolver(container);

This is basically what’s in the Autofac documentation.

Notice how we need to set up Autofac for both MVC and WebAPI. This is because this application is using both. I’m using standard MVC Controllers for regular views, and WebAPI ApiControllers for the AJAX calls from my Angular SPA. This is probably something I could refactor later.

After having done this, nothing much has changed in our code, but an important change has happened at runtime: Autofac now creates the Controllers and any constructor dependencies. Of course, we don’t have any constructor dependencies yet, because we were instantiating dependencies ourselves. We can easily change that.

Take our MatchController for example:

public class MatchController : ApiController
{
    private readonly MatchesContext _matchesContext = new MatchesContext();

    [HttpGet]
    public IList<Match> Get(int id)
    {
        var matches = _matchesContext.Context.Matches.Where(x => x.TournamentId == id).OrderBy(x => x.DateTime).ToList();

        return matches;
    }
}

Because Autofac takes care of our dependencies, we can change it to this:

public class MatchController : ApiController
{
    private readonly MatchesContext _matchesContext;

    public MatchController(MatchesContext matchesContext)
    {
        _matchesContext = matchesContext;
    }

    [HttpGet]
    public IList<Match> Get(int id)
    {
        var matches = _matchesContext.Context.Matches.Where(x => x.TournamentId == id).OrderBy(x => x.DateTime).ToList();

        return matches;
    }
}

Now all we need to do is register the MatchesContext so that Autofac knows it has to provide this to the MatchController. So we add this line after registering our controllers:

builder.RegisterType<MatchesContext>();

That’s how easy it often is to get started with dependency injection. This is just the starting point, but it’s a powerful one. You can now work your way into the dependency chain and start moving the responsibility of creating dependencies towards Autofac. You can also start using interfaces for dependencies so that you can more easily test components.

Over time, your application will start being built up of loosely coupled components that can more easily be tested, refactored and moved around.

You can see the entire commit that introduced Autofac here.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.