.NET Core Dependency Injection

In today’s time, when it comes to app development, an Object Oriented programming approach is used and to make the right use of this concept, the ASP.NET Core framework is the best option. But when it comes to the object-oriented approach, it is all about objects and class and the creation of complex applications. Things can get cluttered if the developers do not follow any specific design pattern to control the development and lifetime of these objects. Therefore, .NET development companies follow software design patterns and principles like Dependency Injection to write more manageable, flexible, and easy-to-test software. To know more about .NET Core Dependency Injection design patterns, let’s go through this blog.

1. What is Dependency Injection?

Dependency injection (DI) is a very popular technique that is used by developers for programming applications. This process enables the .NET developers to create an independent class of its dependencies. Generally, it happens that the developers don’t create objects of other dependencies (classes) in the code directly but ask the DI container to develop objects of dependency classes. After they are created, they are injected into the classes so that they can be used in the code.

Let’s get a clear idea about dependency injection by going through the following example –

In an application, when class A starts using some of the functionalities of class B, it is said that class A has a dependency on class B. This means that when it’s time to call any method of class B, the developer needs to create an object of class B inside class A. This can help in using the functionality of class B with ease.

If it happens that after some time, the requirement of the application changes and the developer needs to replace the class B functionalities, with a new class named class C, there might be big issues as the objects created in class B are present in many different places. And because of this, changes in the code are required which might be everywhere in the application. The reason behind it is that the classes are generally tightly coupled, making it impossible to replace the functionalities of class B with class C without making changes in the current code. To overcome all these issues, dependency injection is used.

2. Benefits of Dependency Injection

Here are some of the major benefits of dependency injection –

  • For implementing dependency injection, the developers can easily follow a unit testing approach by injecting one class or another in the application services.
  • Dependency injection offers flexible and maintainable code by making the implementation of the class without changing the business logic or code in the application. Here the code becomes easy to read as the creation or initialization of dependencies is outside the code.
  • The help of dependency injection makes it easy for the developers to extend the application as they cannot only introduce new components but can also help with multiple implementations of good versions of the existing components and then finally inject those components into the application.
  • The dependency injection design pattern enables loose coupling of the components of any application.
  • Generally, programs are more maintainable, testable, and reusable. And this is because the client’s knowledge is removed when it concerns the implementation of dependencies.
  • Another benefit of .Net Core framework dependency injection is that it relieves multiple code modules of instantiating references to enable dependencies and references from the task even mock dependencies are to be swapped out easily. Basically, dependency services enable the framework to do the creation of resources, the configuration of resources, updates, and configuration data centralized in one place.
  • With the help of Extensible Markup Language files, injected resources can be customized outside the source code. Besides, this can also allow changes to be applied without the need to recompile the codebase of the application.
  • Dependency injection enables unit testing which can externalize configuration information into configuration files and makes it possible for the system to be reconfigured without any need for recompiling.
  • Another benefit of DI is that it enables the developers to create classes like public class, implementation class, entity framework contexts, and more independently.

3. Dependency Injection in ASP.NET Core

Here is how the dependency injection design pattern works .Net core and enables developers to create robust web apps.

Initially, developers were using frameworks and libraries like Castle Windsor, Autofac, or Unity for implementing Dependency Injection in clients’ projects. But after dependency injection became a part of ASP.NET Core, all the framework services like Logging, Configuration, Routing, and more are now registered in a built-in dependency injection container and then they are offered as services when required by client request. Basically, each managed framework service is defined to offer a specified service type approach when required by single request.

The concept dependency services is used to register all services when the ASP.NET Core application starts and then these services are injected and resolved at runtime. Besides this framework service, ASP.NET Core Dependency Injection Framework and its classes called services are also available in a namespace called Microsoft.Extensions.DependencyInjection along with two essential & widely used components. These components are as follows –

  • IServiceProvider: In the service collection of .NET dependency injection, this interface is utilized by the web application developers in order to resolve service instance-based issues by looking up at what the interface belongs to and what concrete implementation process is followed or how the implementation is carried out for the creation of framework service.
  • IServiceCollection: Another interface is IServiceCollection which is a standard method to utilize each Dependency Injection service instance in .NET Core applications. The use of this interface is carried out by the developers when it comes to registering all the services that are required to resolve and inject later on into the application. We want to resolve this and inject it later into our application. For all the IServiceCollection services, the startup class offers the ConfigureServices method in which the service instance of the IServiceCollection approach is available as a parameter.

4. ASP.NET Core Service Lifetime

Here are the details about the lifetime of the ASP.NET Core Service instances :

4.1 Singleton

In singleton services, the creation, storage in memory, and reusability of a single service type class instance are carried out throughout the application. The .NET developers can utilize Singleton for registered services that are costly to instantiate. Here experts of dependency service type can also use this approach in scenarios where they want to share states across various components. Besides this, one thing that must be considered while using this approach is thread safety as the single service instance is created once and can be accessed by many clients.

The singleton service can be registered by a single instance using the AddSingleton method as shown below –

services.AddSingleton<IProductService, ProductService>();

4.2 Scoped

Scoped is another service registered in the .NET core dependency injection. It can be created once as per a client’s request. In scoped service, all the middleware like MVC controllers and more that have the capability to handle a single request will get the same instance as a response in spite of a new instance. Basically, in scoped services, a good candidate is an Entity Framework context. In a scoped lifetime, its registration is carried out using the AddScoped method as shown below –

services.AddScoped<IProductService, ProductService>();

4.3 Transient

Another .NET core service is Transient lifetime services. It is developed every time a client requests it. These  Transient services work best for stateless and lightweight application services. It is a great default choice for developers when they don’t know which life should be used because each client will get a service copy and here the thread safety will not be a problem. To register the Transient service the developers use the AddTransient method as shown below –

services.AddTransient<IProductService, ProductService>();

5. ASP.NET Core Dependency Injection Example

Here is an example of ASP.NET Core dependency injection that will give you a clear idea of how it works –

The following example  below consists of the IProductRepository public interface and ProductRepository class which implements this interface:

public class ProductRepository: IProductRepository
{
	public Product GetProduct()
	{
		return new Product();
	}
}
public interface IProductRepository
{
	Product GetProduct();
}

In this code, the interface used is just like a contract. This means that the class that implements this public interface, should also be able to implement all methods that are demanded by this interface. For instance, if the class here which is called ProductRepository does not implement the GetProduct method. There will be an error in the output and the reason behind it is that the interface demands that the GetProduct method needs to be implemented in the ProductRepository class.

Therefore, to avoid such errors, the dependent services should be registered into the service container via a method called ConfigureServices in the Startup class. To understand this clearly, look at the example given below on how the interface IProductRepository is set up dependent services through this interface and how it can resolve the error. Check the instance of ProductRepository class given below:

public void ConfigureServices(IServiceCollection services)
{
	services.AddScoped();
}

Once this configuration process is carried out, whenever an instance is required for this class, it will be created. This makes it possible for the developers to use the ProductRepository class in the ProductService class  by utilizing the dependency injection via the constructor of the class:

public class ProductService
{
	private readonly IProductRepository ProductRepository;
	public ProductService(IProductRepository ProductRepository)
	{
		ProductRepository = ProductRepository;
	}
}

The constructor stated above accepts a IProductRepository parameter and then it makes it possible to store the dependency in a private field that is ready only. Setting the property to implement dependency injection as a read-only will help in avoiding the possibility of various different methods being accidentally assigned a different value for this dependency injection. After this property injection is done, the class can now use abstraction.

With dependency injection, the code doesn’t depend on the concrete class (ProductRepository) but it depends on an abstraction (IProductRepository). This property injection means that the registered service ProductService is not using ProductRepository, the concrete type, and is only using the IProductRepository interface. Basically, this property injection method of coding makes it easy to change the ProductRepository implementation that can be utilized by the registered service class, without any requirement for modification in the service class itself.

In addition to this, the service class in this code will also not create an instance of ProductRepository, as it is only developed by the dependency injection container. By following this method, the code remains loosely coupled, so when there is a change in the concrete class (ProductRepository), there will be no break in the code that is present on the ProductService as the code only depends on the abstraction.

6. Conclusion

As seen in this blog, there are many different concepts that are related to the Dependency Injection design pattern which comes with various benefits. The ASP.NET Core service lifetime using dependency injection is unique. It can help the developers configure an ASP.NET Core application to utilize the register services and the built-in service container within IoC. This means that .NET Core dependency injection can be used in various different scenarios to make the application stand out. 

profile-image
Itesh Sharma

Itesh Sharma is core member of Sales Department at TatvaSoft. He has got more than 6 years of experience in handling the task related to Customer Management and Project Management. Apart from his profession he also has keen interest in sharing the insight on different methodologies of software development.

Comments

  • Leave a message...