CodeBlanks Logo Icon CodeBlanks

Constructor injection

C# course · Advanced · Lesson 56/83

Learn to pass dependencies through constructor injection.

Constructor injection

Constructor injection passes the dependency as a parameter to the class's constructor. The received dependency is stored in a private readonly field. This is the most common DI pattern.

Constructor injection guarantees the dependency will not change during the class's lifetime. The readonly keyword ensures the field can only be assigned in the constructor; it cannot be changed afterwards. In tests, fake dependencies can be passed easily.

The readonly field

The dependency is stored as private readonly ILogger _logger;. readonly means the field can only be assigned in the constructor (or at declaration); it cannot be changed afterwards.

This guarantees the dependency's immutability and prevents accidental reassignment. In tests, when you want to swap the real logger for a fake, you just create a new instance and pass it to the constructor; you cannot mutate the existing instance's field.

Exercise Pass two dependencies through the constructor

Define the constructor of the Service class below with the signature public Service(ILogger logger, IRepo repo). In the body assign _logger = logger; and _repo = repo;. In Main create the instance with new Service(new ConsoleLogger(), new FakeRepo()) and call s.DoWork().

Show example solution
public Service(ILogger logger, IRepo repo) { _logger = logger; _repo = repo; }. In Main: Service s = new Service(new ConsoleLogger(), new FakeRepo()); s.DoWork();
Example solution:
using System;

interface ILogger { void Log(string msg); }
interface IRepo { string Get(); }

class ConsoleLogger : ILogger
{
    public void Log(string msg) => Console.WriteLine(msg);
}

class FakeRepo : IRepo
{
    public string Get() => "Data";
}

class Service
{
    private readonly ILogger _logger;
    private readonly IRepo _repo;
    public Service(ILogger logger, IRepo repo)
    {
        _logger = logger;
        _repo = repo;
    }
    public void DoWork() => _logger.Log(_repo.Get());
}

class Program
{
    static void Main()
    {
        Service s = new Service(new ConsoleLogger(), new FakeRepo());
        s.DoWork();
    }
}

Test yourself

  1. Complete the constructor parameter

    public Service(ILogger ____) { _logger = logger; }
    Show answer
    public Service(ILogger logger) { _logger = logger; }
  2. Where is the dependency stored in constructor injection?

    • In a local variable
    • In a static field
    • In a property
    • In a private readonly field
    Show answer

    In a private readonly field — Correct. The dependency is stored in a private readonly field.

  3. Match the pattern to its behavior

    Constructor injection
    Passes via constructor
    Property injection
    Passes via property
    Method injection
    Method parameter
    Service locator
    Class pulls

All lessons in Advanced