Dependency Injection

Dependency Injection is a way to implement Inversion of Control (IoC). In this case, a dependency is an object that another object depends on. It involves abstracting classes into interfaces, so that the interface can be injected into the constructor of classes which depend on it. This allows implementation details to be changed at compile-time (e.g., to be used for automated testing), but does not change how things run at run-time.

Here's an example of code without dependency injection

public class Worker : BackgroundService
{
    // INSTANTIATING THE DEPENDENCY AS AN OBJECT
    private readonly MessageWriter _messageWriter = new();

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
            await Task.Delay(1_000, stoppingToken);
        }
    }
}

Here's an example of code with dependency injection

namespace DependencyInjection.Example;

// THE DEPENDENCY IS PASSED IN THE CONSTRUCTOR, USING AN INTERFACE
public sealed class Worker(IMessageWriter messageWriter) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            messageWriter.Write($"Worker running at: {DateTimeOffset.Now}");
            await Task.Delay(1_000, stoppingToken);
        }
    }
}