Select Page

Dependency Injection in ASP.NET Core 3.1

by | May 31, 2020 | Programming | 0 comments

ASP.NET Core is designed from the ground up to support the dependency injection design pattern. Dependency injection in ASP.NET Core provides a technique to create applications that are loosely coupled. ASP.NET Core allows us to injects dependent objects either through constructor or methods. Based on the environment in which application is running different objects can be injected.

What is Dependency Injection?

Dependency Injection in ASP.NET Core

Dependency injection is used to achieve loose coupling in application between client objects and their dependencies. Instead of directly instantiating objects of classes and using them rather Interfaces are used and objects are provided to class in some way either through constructor or through some method.

Class will depend on an interface rather than concrete implementation of dependencies. This makes our code loosely coupled as we can inject any concrete object as far as it implements the required interface.

ASP.NET Core comes with a built-in container (IServiceProvider) that supports constructor injection by default and the framework itself provides some services through dependency injection.

Here is a great article by Martin Fowler on Dependency Injection

Why Dependency Injection

  • Improves code readability by keeping it clean so easier to maintain it.
  • Application is loosely coupled which improves flexibility
  • Increases code testing ability with different mock implementations of services.
  • Supports extendable class structure

Implementation of Dependency Injection in ASP.NET Core

There are two types of services in ASP.NET Core

  1. Framework provided services – These services are part of ASP.NET Core framework
  2. Custom Services – These are add-on services created by developers

Registering framework provided services

Below code shows how to register a framework defined service (Memory Caching Service) in ConfigureServices() method of startup.cs

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddMemoryCache();
    }
    //Remaining code was removed
}

Registering your own services

You can even register your own service and make it available for dependency injection into controllers, middlewares & views

First you need to define the service using an interface as shown below

public interface ILogger
{
    void Log(string message);
    void Log(string message, Exception ex);
}

public class LogToFile : ILogger
{
    public void Log(string message)
    {
        //Log Message to File
    }

    public void Log(string message, Exception ex)
    {
        //Log Message & Exception to File
    }
}

public class LogToDB : ILogger
{
    public void Log(string message)
    {
        //Log Message to Database
    }

    public void Log(string message, Exception ex)
    {
        //Log Message & Exception to Database
    }
}

Service Lifetime

Before we talk about how to register your service in the startup.cs file we need to understand the significance of Service Lifetime while registering a service. Lifetime decides whether the instance of a service being injected is a new instance to that component or it same signal instance which is being used everywhere in the application. While registering service you need to choose the lifetime for each service.

Transient – Each time a new object is created for dependency injection i.e. each component will have its unique instance. This is the option used for lightweight & stateless services.

services.AddTransient<ILogger, LogToFile>();

Scoped – This means that it is created once for each request i.e. a new object will be created for each new request.

services.AddScoped<ILogger, LogToFile>();

Singleton – One single component will be created for the lifetime of the application. This single instance is shared across all components and all requests.

services.AddSingleton<ILogger, LogToFile>();

Registering Services in startup.cs

You need to register required services in ConfigureServices() methif of startup.cs

public class Startup
{
    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddControllersWithViews();
        services.AddMemoryCache();

        services.AddTransient<ILogger, LogToDB>();
    }
     //Remaining code has been removed
}

Once service is registered it can be injected into other components

Newsletter Subscription

Stay updated! Instantly get notified about my new articles in your mailbox by subscribing via email

Injecting services (framework/custom) into Middleware

Below is the code sample for the injection of service into middleware. Either it can be injected through the constructor and or through the invoke method.

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger _logger;
    private readonly IMemoryCache _cache;

    public ExceptionMiddleware(RequestDelegate next, ILogger logger, IMemoryCache cache)
    {
        _next = next;
        _logger = logger;
        _cache = cache;
    }

    public Task Invoke(HttpContext httpContext, ILogger logger, IMemoryCache cache)
    {
        return _next(httpContext);
    }
}

Injecting services (framework/custom) into Controller

Below is the code sample for the injection of service into the controller. Either it can be injected through the constructor and or through the action method.

public class HomeController : Controller
{
    private readonly ILogger _logger;
    private readonly IMemoryCache _cache;

    public HomeController(ILogger logger, IMemoryCache cache)
    {
        _logger = logger;
        _cache = cache;
    }

    public IActionResult Index([FromServices] ILogger logger, [FromServices] IMemoryCache cache)
    {
        return View();
    }
}

Request Services Manually

Instead of using dependency injection to inject services, components can even manually request services. Below code shows how to manually request a service using HttpContext object.

var services = this.HttpContext.RequestServices;
var log = (ILogger)services.GetService(typeof(ILogger));

Summary

Dependency injection allows us to develop loosely coupled applications. Dependency injection in ASP.NET Core is supported and also it is simple and easy to implement. Framework provided services or your own custom services can be used for dependency injection.

You can inject components using dependency injection into middlewares, controllers, view, etc. Service lifetime can be used to control the scope of the service.

References: https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.1

You can also check my another Article on Microsoft Azure Storage – https://procodeguide.com/programming/azure-storage/

Hope you found this article useful
Buy me a coffeeBuy me a coffee

0 Comments

Submit a Comment

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

Credit card sized computer, Home Automation and much more with Raspberry Pi 4

Improve performance of your laptop by replacing hdd with ssd