Summary - DI
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
-
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.
-
Match the lifetime to its instance count
- Singleton
- 1 (app)
- Scoped
- 1 (scope)
- Transient
- Unlimited (per call)
- AddSingleton
- Register method