Click here to Skip to main content
15,867,330 members
Articles / Web Development / ASP.NET

Dependency Injection Before ASP.NET Core

Rate me:
Please Sign up or sign in to vote.
4.93/5 (6 votes)
3 Aug 2017CPOL3 min read 14K   4   2
Dependency injection before ASP.NET core

Introduction

Wikipedia says: "Dependency injection is a software design pattern in which one or more dependencies (or services) are injected, or passed by reference, into a dependent object (or client) and are made part of the client's state. The pattern separates the creation of a client's dependencies from its own behavior, which allows program designs to be loosely coupled and to follow the dependency inversion and single responsibility principles. It directly contrasts the service locator pattern, which allows clients to know about the system they use to find dependencies.".

So, from Wikipedia definition, we resume that Dependency Injection (DI) is a technique used to loose coupling between objects or dependencies. It is a sub-approach forming part of the global concepts of inversion of control. Its principle is such that a subroutine must express the dependencies it needs to function. The IoC container is then used to instantiate the subroutine; Taking into account these dependencies. The injection of dependencies can take several forms: via a constructor, via a property, via a private field, and so on. This depends on the library used and the conceptual choices used in the project.

This technique is used always when we would like to manage dependencies and to develop a modular and well-structured application.

Background

To understand this article, you need to be able to create a Console application and integrate libraries.

Dependency Injection in MVC

It is possible to easily transpose the principle of injection of dependencies in the following way. The controller here expresses its dependencies via its constructor.

C#
public class DIController : Controller
{
    private readonly IDependencyInjectionService _dependencyInjectionService;
    public MyController(IDependencyInjectionService dependencyInjectionService)
    {
        _dependencyInjectionService = dependencyInjectionService;
    }
}

//And in the main class 
static void Main(string[] args)
{
    var unityContainer = new UnityContainer();
    unityContainer.RegisterType<IDependencyInjectionService , DependencyInjectionService>();
    var instance = unityContainer.Resolve<DIController>();}

Before ASP.NET Core

The previous example is a bit special. Indeed, if you run it as is, at runtime, the program does not work.

Indeed, the default behavior of the controller factory is to expect that the default constructor (without arguments) is present on the controllers to be instantiated. The factory uses the Activator class of the.NET Framework and its CreateInstance method.

With ASP.NET MVC 4 and 5, the solution usually consists of replacing the dependency resolution mechanism of the library (the DependencyResolver class) with an implementation connected to the IoC container.

With ASP.NET Web API 1 and 2, it is also necessary to replace a service in the library with an implementation plugged into the IoC container. However, the differences in internal operation between the two libraries mean that the service to be replaced is not exactly the same.

Using a library such as Unity, it is possible to retrieve a NuGet package adapted to ASP.NET MVC which automatically downloads the Bootstrapper class below. Notice the call to the SetResolver method of the DependencyResolver class. It is this call that makes it possible to replace the mechanism of resolution and instantiation of the services for all the ASP.NET MVC part of an application. Let's start with an example:

C#
public static class UnityConfig
{
  public static IUnityContainer Initialise()
  {
    var container = BuildUnityContainer();

    DependencyResolver.SetResolver(new UnityDependencyResolver(container));

    return container;
  }

  private static IUnityContainer BuildUnityContainer()
  {
    var container = new UnityContainer();

    RegisterTypes(container);

    return container;
  }

  public static void RegisterTypes(IUnityContainer container)
  {
      container.RegisterType<IDependencyInjectionService , DependencyInjectionService>();
  }
}

The instance passed to SetResolver must simply implement an IDependencyResolver interface, which is present in the System.Web.Mvc namespace.

C#
public interface IDependencyResolver
{
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

Reference: https://msdn.microsoft.com/en-us/library/system.web.mvc.idependencyresolver(v=vs.118).aspx

And it is at this level that the simple implementation by default and using the Activator class is defined. It is this class that we replace when we use the SetResolver method.

C#
private class DefaultDependencyResolver : IDependencyResolver
{
    public object GetService(Type serviceType)
    {
        if (serviceType.IsInterface || serviceType.IsAbstract)
        {
            return null;
        }
        try
        {
            return Activator.CreateInstance(serviceType);
        }
        catch
        {
            return null;
        }
    }

    public IEnumerable<object> GetServices(Type serviceType)
    {
        return Enumerable.Empty<object>();
    }
}

With ASP.NET Web API 2, implementation requires the creation of a class that meets the IDependencyResolver contract. The namespace of the latter is System.Web.Http.Dependencies.

C#
public interface IDependencyResolver : IDependencyScope, IDisposable
{
    IDependencyScope BeginScope();
}

public interface IDependencyScope : IDisposable
{
    object GetService(Type serviceType);
    IEnumerable<object> GetServices(Type serviceType);
}

The instantiation and definition of the Resolver so that it can be used with the Web API controllers is ultimately done in a totally different way.

C#
public static void Register(HttpConfiguration config)
{
    var container = new UnityContainer();
    container.RegisterType<IDependencyInjectionService, DependencyInjectionService>();

    config.DependencyResolver = new UnityResolver(unityContainer);

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}

Note that both technologies, ASP.NET MVC and ASP.NET Web API have the basics to enable injection of dependencies. The DependencyResolver mechanism is present as a base. However, by default, it is not plugged into an IoC container. In addition, each technology uses its own mechanism. For an application that mixes MVC and Web API controllers, it is, therefore, necessary to create two DependencyResolver homes and plug them into the same IoC container.

Note that SignalR, another ASP.NET brick also has its own mechanism, also different from those presented above.

Blog link: http://hamidarebai.blogspot.it/2017/07/dependency-injection-in-aspnet-core-di.html

History

  • 3rd August, 2017: Initial version

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Technical Lead
Canada Canada
I am Rebaï Hamida, Microsoft MVP in Visual Studio and Development Technologies.
I'm a software architect and developer who like to build open source projects, writing articles, learning and teaching best practices. you can find out in my blog : http://hamidarebai.blogspot.com/

Innovative Software engineer : hands-on, competent software engineer, passionate and proficient C# developer, offering more than seven years of experience in the full software development lifecycle – from concept through delivery of next-generation applications and customized solutions, producing code to a consistently high standard and testing software across a variety of platforms.
Expert in advanced development methodologies, tools and processes contributing to the design and roll-out of cutting-edge software applications.
Known for excellent troubleshooting skills – able to analyze code and engineer well-researched, cost-effective and responsive solutions.


Success is only a consequence of a continuous work and remarkable intelligence.
I believe that I have to make a change in my country, I can’t live without leaving my footprint.

Comments and Discussions

 
SuggestionInteresting Pin
RickZeeland4-Aug-17 9:31
mveRickZeeland4-Aug-17 9:31 
GeneralRe: Interesting Pin
didourebai8-Aug-17 0:44
professionaldidourebai8-Aug-17 0:44 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.