Asp.net Core 1.1 Dependency Injection VS 2017

Dependency Injection is an important pattern, one of the five SOLID principles of software engineering.

Traditionally procedural programming takes control from the start of the execution and use a lot of conditional statements to execute the exact configurations that the system is tuned for.

In modern development number of people write small components performing different tasks and wire them together to make an application work. These components can be as simple as a class or a library. Wiring them together is where the inversion of control or dependency injection plays its role. Your code will start execution just like traditional approach but as soon as it reaches a custom written component having two or more implementations, the DI (Dependency Injection) framework will automatically load the desired component.

There are number of DI frameworks available in the market like Unity, Autofac and StructureMap. Microsoft with previous versions of Asp.net Mvc, was officially using Unity. Unity is no longer being maintained. MSDN has following to say

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies. This page may contain URLs that were valid when originally published, but now link to sites or pages that no longer exist.

Since the launch of Asp.net Core Mvc, Microsoft has built-in dependency injection module.

Cross Cutting Concern

Dependency is related to non functional requirements of an application and helps in making applications scale-able and manageable. We call it a cross cutting concern because it equally plays an important role in all of the layers in an application.

Dependency

How to identify the dependencies? Its really simple. You need to divide your application into smaller possible components. Lets assume the smallest component we are talking about is a class. A class provides the definition of attributes and behaviors, of an object. An object can perform certain responsibilities (behaviors). To perform these responsibilities they may need to initiate other smaller components. Tada! here comes the dependency. Your class was knowingly or unknowingly depending on those other smaller components.

Asp.net Core Built-in Container

Asp.net core comes with a simple built-in container represented by the interface IServiceProvider. Default implementation of IServiceProvider manages types (Interfaces or classes) and commonly refer them as services. If you look back at Startup.cs class that is responsible to boot the Asp.net Core and create a request pipeline before accepting any request, you must have noticed the following method

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();
    services.AddTransient<Person>();
}

IServiceCollection is the collection of services (types of interfaces and classes) that are registered with built-in IServiceProvider. You can add/register more services in ConfigureServices() method.

By default constructor injection is supported. But with a little variation we can use property injection as well as action/method injection.

Constructor Injection

The constructor needs to be public. If constructors are overloaded and more than one constructors can be resolved by the container, it will become a problem to choose which one to resolve. Lets start with a small class.

Lets add this class in our models and try to use this class in the constructor of our controller.

HomeController is dependent on Person class as can be easily observed in the constructor. Trying to browse index action will throw an exception.

An unhandled exception occurred while processing the request.

InvalidOperationException: Unable to resolve service for type ‘VenueApp.Models.Person’ while attempting to activate ‘VenueApp.Controllers.HomeController’.

Asp.net Core tried to resolve the dependency using default service resolver, but failed because we have not registered Person as a service with default container. Therefore default container (IServiceProvider) do not know about the definition/implementation of Person. Lets add the Person class in the services.

At line number 10, the Person class is registered as a service with default container. Once registered, the Person class dependency is resolved and Index action will greet the programmer as an output.

Registering Services

Services can be registered using three different methods. Each method helps programmers to define the life span of the object that will be created while resolving the service.

Transient Services

Transient services are registered using following method or its overloads.

services.AddTransient();

If a class/interface is registered as a transient service, each time it resolves the container will entertain with a new object. If objects are small, stateless and shouldn’t be held in the memory for long Transient is the perfect choice.

Scoped Services

Scoped services are registered using following method or its overloads.

services.AddScoped();

Scoped services are initiated for only once by the container for one request. For the rest of the request pipeline no matter how many times it is resolved same object is returned for scoped services.

Singleton Services

Singleton services are initiated on the first request and later for every other service the same object is returned. Singleton services resides in memory for the lifetime of application and should be used carefully. Singleton services can be registered using

services.AddSingleton();

As I mentioned in the beginning you can also use property or action injection with a little variation. We can use an attribute [FromServices] with action arguments.

public IActionResult Greet([FromServices] Person Owner) {
    ContentResult content = new ContentResult();
    content.Content = "Hello " + Owner.Name;
    return content;
}

Using this attribute is only allowed with the method arguments and it will work only with controller methods as they are identified and resolved by the Asp.net Core after routing determine which action is to be called.

To inject a property you will need to use the service locator anti-pattern

Person Owner = (Person) HttpContext.RequestServices.GetService(typeof(Person));

Injection in Views

You can use @inject directive for razor views to inject services directly into the views.

@inject Person programmer
<div> @programmer.Name</div>

Injection works with Filters, Routing, Authorization handlers and other components of Asp.net core.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s