CodeBlanks Logo Icon CodeBlanks

Summary - DI

C# course · Advanced · Lesson 60/83

Combine ServiceCollection and lifetimes to write a simple service registry.

Summary - DI

In this group you learned DI basics, constructor injection, ServiceCollection and the Singleton, Scoped and Transient lifetimes. Combining these, you can build a simple service registry.

First you will register and resolve multiple services, then compare Singleton and Transient behaviors side by side. This is a summary of real-world DI usage.

Exercise Register and invoke multiple services

In Main, create the container with var services = new ServiceCollection();. Register two services as singleton: services.AddSingleton<ILogger, ConsoleLogger>(); and services.AddSingleton<ICounter, StaticCounter>();. Build the provider with var provider = services.BuildServiceProvider();. Resolve with var logger = provider.GetRequiredService<ILogger>(); and var counter = provider.GetRequiredService<ICounter>();. Call with logger.Log(counter.Next().ToString());.

Show example solution
services.AddSingleton<ILogger, ConsoleLogger>(); services.AddSingleton<ICounter, StaticCounter>(); var provider = services.BuildServiceProvider(); var logger = provider.GetRequiredService<ILogger>(); var counter = provider.GetRequiredService<ICounter>(); logger.Log(counter.Next().ToString());
Example solution:
using System;
using Microsoft.Extensions.DependencyInjection;

interface ILogger { void Log(string msg); }
interface ICounter { int Next(); }

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

class StaticCounter : ICounter
{
    private int _count;
    public int Next() => ++_count;
}

class Program
{
    static void Main()
    {
        var services = new ServiceCollection();
        services.AddSingleton<ILogger, ConsoleLogger>();
        services.AddSingleton<ICounter, StaticCounter>();
        var provider = services.BuildServiceProvider();
        var logger = provider.GetRequiredService<ILogger>();
        var counter = provider.GetRequiredService<ICounter>();
        logger.Log(counter.Next().ToString());
    }
}

Exercise Demonstrate Transient behavior

In Main, create the container with var services = new ServiceCollection();. Register ICounter as transient with services.AddTransient<ICounter, Counter>();. Build the provider with var provider = services.BuildServiceProvider();. Resolve twice with var c1 = provider.GetRequiredService<ICounter>(); and var c2 = provider.GetRequiredService<ICounter>();. Print Console.WriteLine(c1.Next()); and Console.WriteLine(c2.Next());.

Show example solution
services.AddTransient<ICounter, Counter>(); var provider = services.BuildServiceProvider(); var c1 = provider.GetRequiredService<ICounter>(); var c2 = provider.GetRequiredService<ICounter>(); Console.WriteLine(c1.Next()); Console.WriteLine(c2.Next());
Example solution:
using System;
using Microsoft.Extensions.DependencyInjection;

interface ICounter { int Next(); }

class Counter : ICounter
{
    private int _count;
    public int Next() => ++_count;
}

class Program
{
    static void Main()
    {
        var services = new ServiceCollection();
        services.AddTransient<ICounter, Counter>();
        var provider = services.BuildServiceProvider();
        var c1 = provider.GetRequiredService<ICounter>();
        var c2 = provider.GetRequiredService<ICounter>();
        Console.WriteLine(c1.Next());
        Console.WriteLine(c2.Next());
    }
}

Test yourself

  1. What does AddSingleton do?

    • Creates a new instance per request
    • Gives a separate instance per scope
    • Only debugs
    • Gives a single instance for the whole app
    Show answer

    Gives a single instance for the whole app — Correct. AddSingleton gives a single instance for the whole app.

  2. Match the lifetime to its instance count

    Singleton
    1 (app)
    Scoped
    1 (scope)
    Transient
    Unlimited (per call)
    AddSingleton
    Register method

All lessons in Advanced