Dependency Injection to The Core (Part - III)

We came to know about the term IoC container. There are many IoC containers available and most of them do the same things somewhat differently. Let’s use one of them in our current project. Let’s pick Autofac which has a great documentation online. Here is the link where you can know all about the Autofac integration related stuff with Web API projects,

http://autofac.readthedocs.io/en/latest/integration/webapi.html

Since we are just beginners wondering around the world of dependency injection. We will go slow and easy. The Autofac library for Web API projects is available to download to from Nuget,

Install-Package Autofac.WebApi2

I’ve downloaded it in my Techtalkers.WEB project. Time to configure it. I’ve created a class in the App_Start folder and added this method where I’ve configured Autofac like this.


public class AutofacConfig
{
    public static void RegisterAutofac()
    {
        var builder = new ContainerBuilder();

        var config = GlobalConfiguration.Configuration;
        builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
        builder.RegisterType<TodoRepository>().As<ITodoRepository>().InstancePerRequest();

        var container = builder.Build();
        config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
    }
}

Here we get the HttpConfiguration which is basically the GlobalConfiguration.Configuration. Registered all the Api controllers available in the current assembly (Techtalkers.WEB). Then registered the TodoRepository so that a new instance of it can be served whenever we have ITodoRepository in the request scope. Notice that we can define lifetime for a specific instance. Here InstancePerRequest() will create a new singleton instance of TodoRepository per request and shared across the nested parentand nested scopes. You can define different lifetimes for your service instance just by using the other extension methods available from Autofac. And this is actually a great functionality available in all the Ioc containers. Lastly, we have built the container and passed it in the AutofacWebApiDependencyResolver. This class basically implements the IDependencyResolver interface provided by the Web API project. That’s it. From now on Autofac will resolve all the dependencies for our project. We don’t have to bother about how it will do it. Thing is it will do it. And if you are interested in the raw implementation then you can check the github repository for Autofac. This is an open-source project.

Next, we have to called the RegisterAutofac() from the Global.asax.cs. There, the Application_Start() is called every time the application is started. So like the other registration stuff, I’ve registered the RegisterAutofac() method there.


protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    GlobalConfiguration.Configure(WebApiConfig.Register);
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);

    AutofacConfig.RegisterAutofac();
}

Now, we are in a situation where we can easily test our TodoController. We don’t have to worry about instantiations of concreate repositories since we are no longer depend on any of them. Instead we can use a mock repository whenever we are in the test. A library called Moq can help us do that. A simple test for the Get() method will look like this,


public class TestTodoControlloer
{
    [TestMethod]
    public void GetAll_ShouldReturnAllTodos()
    {
        // Arrange
        var mockRepository = new Mock<ITodoRepository>();

        mockRepository.Setup(x => x.GetAll())
            .Returns(new List<Todo>()
            {
                new Todo() {Id = 1, Title = "Test Item 1", IsDone = true},
                new Todo() {Id = 2, Title = "Test Item 2", IsDone = true},
                new Todo() {Id = 3, Title = "Test Item 3", IsDone = false}
            });

        var controller = new TodoController(mockRepository.Object);

        // Act
        var todoes = controller.Get();

        // Assert
        Assert.IsNotNull(todoes);
        Assert.AreEqual(3, todoes.Count());
        Assert.AreEqual(2, todoes.Count(t => t.IsDone));
    }
}

As you can see here, we don’t have to create a concrete repository type to pass it around in the controller. We can just simply use a mock object instead.

Now that we have some get to go understanding on DI, we can make a tour to the wonderful world of .net core and see how DI is done there. .Net core by default provides some bare minimum functionality to do DI. But most of the time it’s enough for even big project that has hundreds of dependencies. For the time being .net core’s default Ioc container only support construction injection.

So, just like we did with Autofac if you want to serve a concrete TodoRepository instance whenever ITodoRepository get caught in the scope, you would do something like this in the ConfigureServices() method


services.AddScoped<TodoRepository, ITodoRepository>();

As you can see we can define instance lifetime at the same time. Here defining a service in Scoped lifetime means that a new instance of TodoRepository will be created per request and it will be shared in nested scopes.

The two other service lifetimes are Singleton and Transient. And they can be registered like above,


services.AddSingleton<TodoRepository, ITodoRepository >();
services.AddTransient<TodoRepository, ITodoRepository >();

In singleton lifetime, service instances are created the first time they are requested and in subsequent requests the instances will be shared though all the parent and nested scopes.

In transient lifetime, new service instances are created per requests for all the parent and nested scopes.

If you dont feel happy with the built-in functionality you can also add third part IoC containers. Autofac by itself can be used with .net core. You can have a good idea on how to integrate Autofac with .net core in this link below,

http://docs.autofac.org/en/latest/integration/aspnetcore.html

So, that’s it. I guess now you are pretty much comfortable with dependency injection and its related terms. But before you think you are done let me remind you again that these are very much beginner level articles. Also, I only talked about constructor injection. But there is also property injection, method injection, interface injection and etc. I’ll let you do the honor and explore them. Other than lifetime management, you can do a lot with Ioc containers so there are lot of things to learn too. Now go and get your feet wet.