Dependency Injection Basics in C#

Published: (February 27, 2026 at 08:18 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

What is Dependency Injection?

Dependency Injection (DI) is a design pattern that supplies a class with the objects it needs from the outside rather than creating them internally. This makes code more flexible, testable, and maintainable. In the C# and .NET Core ecosystem, DI is supported out of the box.

Example Without DI

public class OrderService
{
    private readonly Logger _logger = new Logger();

    public void CreateOrder(string product)
    {
        _logger.Log($"Order created: {product}");
    }
}

public class Logger
{
    public void Log(string message) => Console.WriteLine(message);
}

In this approach OrderService is tightly coupled to Logger. Replacing the logger requires modifying OrderService.

Example With DI

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

public class ConsoleLogger : ILogger
{
    public void Log(string message) => Console.WriteLine("[Console] " + message);
}

public class FileLogger : ILogger
{
    public void Log(string message) =>
        System.IO.File.AppendAllText("log.txt", message + "\n");
}

public class OrderService
{
    private readonly ILogger _logger;

    // Constructor Injection
    public OrderService(ILogger logger)
    {
        _logger = logger;
    }

    public void CreateOrder(string product)
    {
        _logger.Log($"Order created: {product}");
    }
}

class Program
{
    static void Main()
    {
        // Different loggers can be selected
        ILogger logger = new ConsoleLogger();
        var service = new OrderService(logger);

        service.CreateOrder("Laptop");
    }
}

OrderService now depends on the ILogger interface, allowing any implementation (e.g., ConsoleLogger or FileLogger) to be swapped without changing the service code.

Types of Injection

  • Constructor Injection – dependencies are provided through the constructor (most common).
  • Property Injection – dependencies are assigned via public properties.
  • Method Injection – dependencies are passed as method parameters.

DI in .NET Core

var builder = WebApplication.CreateBuilder(args);

// Register services
builder.Services.AddScoped();
builder.Services.AddScoped();

var app = builder.Build();

app.MapGet("/order", (OrderService service) =>
{
    service.CreateOrder("Phone");
    return "Order processed.";
});

app.Run();

The built‑in DI container automatically creates and injects a ConsoleLogger instance for OrderService.

Service Lifetimes

When registering services, choose a lifetime that matches the intended usage:

LifetimeDescription
TransientA new instance is created every time it is requested.
ScopedA single instance is created per HTTP request.
SingletonA single instance is created at application start and reused throughout the app’s lifetime.
// Transient
builder.Services.AddTransient();

// Scoped
builder.Services.AddScoped();

// Singleton
builder.Services.AddSingleton();
  • Use Transient for lightweight, stateless services.
  • Use Scoped for request‑based services (e.g., DbContext).
  • Use Singleton for shared, application‑wide services.

Benefits of Dependency Injection

  • Loose Coupling – classes depend on abstractions (interfaces) rather than concrete implementations.
  • Testability – easier to substitute mocks or fakes in unit tests.
  • Flexibility – different implementations can be swapped without modifying dependent code.
  • Maintainability – centralised management of dependencies improves readability and reduces duplication.
0 views
Back to Blog

Related posts

Read more »

Why does C have the best file API

2026-02-28 Programming/tags/programming/ Rants/tags/rants/ There are a lot of nice programming languages, but files always seem like an afterthought. You usuall...