Dependency Injection in .NET Core

8 February 2017

Dependency Injection (DI) is one of the core features of .NET Core that allows for cleaner, more maintainable code by promoting loose coupling and enhancing testability. In this post, we’ll dive into Dependency Injection, its importance, and how to configure it in .NET Core to make your applications more modular and easier to test.

1. What is Dependency Injection (DI)?

Dependency Injection is a design pattern used to implement Inversion of Control (IoC), which allows you to inject dependencies (such as services, repositories, etc.) into your classes rather than having them directly instantiated inside the class. This promotes loose coupling between components and makes your application more flexible and easier to maintain.

In .NET Core, DI is built into the framework and is supported out of the box. It allows you to manage services that your application depends on in a central location, and these services are automatically injected into controllers or other components when needed.

2. Why Is Dependency Injection Important?

Here are some reasons why Dependency Injection is a critical pattern in modern development:

  • Testability: By injecting dependencies, you can easily mock or replace services during unit tests, making your code more testable.
  • Maintainability: It promotes single responsibility and separation of concerns, which makes the codebase easier to maintain.
  • Reusability: Components are more reusable because they don’t have direct dependencies on specific implementations.
  • Flexibility: You can easily swap out or replace services without changing the classes that depend on them.

3. Setting Up Dependency Injection in .NET Core

In .NET Core, DI is configured in the Startup.cs file, specifically in the ConfigureServices method. This method allows you to register services that you want to be injected into your controllers or other components.

Let’s start by looking at how you can configure DI in your Startup.cs file.

Example: Setting Up DI in Startup.cs

In the ConfigureServices method of Startup.cs, you can add services to the DI container. These services can then be injected into your controllers, services, or other classes. Here’s an example of how to set it up:

using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Hosting;

namespace MyFirstApi
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
            // Add services to the DI container
            services.AddControllers();

            // Register a custom service (MyService) with DI
            services.AddSingleton<IMyService, MyService>();
        }

        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseRouting();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }
}

In this example, we add a custom service IMyService and its implementation MyService to the DI container. This makes the MyService class available for injection into any class that requires it.

4. Injecting Dependencies into Controllers

Once the service is registered with the DI container, we can inject it into a controller. Let’s create a simple service and inject it into a controller:

Example: Defining a Service

First, create an interface for your service and its implementation:

public interface IMyService
{
    string GetMessage();
}

public class MyService : IMyService
{
    public string GetMessage()
    {
        return "Hello from MyService!";
    }
}

Now, let’s modify the ProductsController from the previous post to inject this service:

using Microsoft.AspNetCore.Mvc;

namespace MyFirstApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class ProductsController : ControllerBase
    {
        private readonly IMyService _myService;

        // Constructor Injection of IMyService
        public ProductsController(IMyService myService)
        {
            _myService = myService;
        }

        // GET: api/products
        [HttpGet]
        public ActionResult<string> Get()
        {
            // Use the injected service
            var message = _myService.GetMessage();
            return Ok(message);
        }
    }
}

In this controller, we inject IMyService through the constructor. The dependency is automatically provided by the DI container when the controller is created. This allows us to call the GetMessage() method from the service within our action.

5. Types of Service Lifetimes

In .NET Core, there are three main lifetimes for services:

  • Transient: Services are created each time they are requested. Use this for lightweight, stateless services. services.AddTransient<IMyService, MyService>();
  • Scoped: Services are created once per request (or per scope). Use this for services that require maintaining state throughout a request. services.AddScoped<IMyService, MyService>();
  • Singleton: Services are created once and shared throughout the application’s lifetime. Use this for services that do not need to be recreated. services.AddSingleton<IMyService, MyService>();

In the example above, we used AddSingleton, meaning that the same instance of MyService will be used across all requests. You should choose the appropriate lifetime based on your service’s requirements.

6. Conclusion

In this post, you’ve learned the basics of Dependency Injection in .NET Core. We’ve covered:

  • What Dependency Injection is and why it’s important.
  • How to configure DI in Startup.cs.
  • How to inject dependencies into controllers.
  • The different service lifetimes in .NET Core.

By using Dependency Injection, you’re able to write more modular, maintainable, and testable code, which is a key part of building high-quality applications. As you continue to develop in .NET Core, you’ll find that DI will become an invaluable tool in your software development toolkit.

Happy coding!

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

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