dictionary.md
June 18, 2026 · View on GitHub
Dictionary
Demonstrates dictionary injection using IReadOnlyDictionary<TKey, TValue>, allowing key-value pair collection injection.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.Bind(Tag.Unique).To((EmailChannel chanel) => new KeyValuePair<Channel, INotificationChannel>(Channel.Email, chanel))
.Bind(Tag.Unique).To((SmsChannel chanel) => new KeyValuePair<Channel, INotificationChannel>(Channel.Sms, chanel))
.Bind(Tag.Unique).To((PushChannel chanel) => new KeyValuePair<Channel, INotificationChannel>(Channel.Push, chanel))
.Bind<INotificationService>().To<NotificationService>()
// Composition root
.Root<INotificationService>("NotificationService");
var composition = new Composition();
var notificationService = composition.NotificationService;
// Verify that all notification channels are injected into the dictionary
notificationService.Channels.Count.ShouldBe(3);
notificationService.Channels[Channel.Email].ShouldBeOfType<EmailChannel>();
notificationService.Channels[Channel.Sms].ShouldBeOfType<SmsChannel>();
notificationService.Channels[Channel.Push].ShouldBeOfType<PushChannel>();
interface INotificationChannel
{
void Send(string message);
}
class EmailChannel : INotificationChannel
{
public void Send(string message) => Console.WriteLine($"Email: {message}");
}
class SmsChannel : INotificationChannel
{
public void Send(string message) => Console.WriteLine($"SMS: {message}");
}
class PushChannel : INotificationChannel
{
public void Send(string message) => Console.WriteLine($"Push: {message}");
}
enum Channel { Email, Sms, Push }
interface INotificationService
{
IReadOnlyDictionary<Channel, INotificationChannel> Channels { get; }
}
class NotificationService(IReadOnlyDictionary<Channel, INotificationChannel> channels) : INotificationService
{
public IReadOnlyDictionary<Channel, INotificationChannel> Channels { get; } = channels;
}
Running this code sample locally
- Make sure you have the .NET SDK 10.0 or later installed
dotnet --list-sdk
- Create a net10.0 (or later) console application
dotnet new console -n Sample
dotnet add package Pure.DI
dotnet add package Shouldly
- Copy the example code into the Program.cs file
You are ready to run the example 🚀
dotnet run
Note
Dictionary injection is useful when you need to access dependencies by keys, such as named or tagged implementations like notification channels.
The following partial class will be generated:
partial class Composition
{
public INotificationService NotificationService
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
Dictionary<Channel, INotificationChannel> transientDictionaryChannelINotificationChannel;
// Creates dictionary entries
KeyValuePair<Channel, INotificationChannel> transientKeyValuePairChannelINotificationChannel;
EmailChannel localChanel = new EmailChannel();
transientKeyValuePairChannelINotificationChannel = new KeyValuePair<Channel, INotificationChannel>(Channel.Email, localChanel);
KeyValuePair<Channel, INotificationChannel> transientKeyValuePairChannelINotificationChannel1;
SmsChannel localChanel1 = new SmsChannel();
transientKeyValuePairChannelINotificationChannel1 = new KeyValuePair<Channel, INotificationChannel>(Channel.Sms, localChanel1);
KeyValuePair<Channel, INotificationChannel> transientKeyValuePairChannelINotificationChannel2;
PushChannel localChanel2 = new PushChannel();
transientKeyValuePairChannelINotificationChannel2 = new KeyValuePair<Channel, INotificationChannel>(Channel.Push, localChanel2);
KeyValuePair<Channel, INotificationChannel>[] localPairs = new KeyValuePair<Channel, INotificationChannel>[3]
{
transientKeyValuePairChannelINotificationChannel,
transientKeyValuePairChannelINotificationChannel1,
transientKeyValuePairChannelINotificationChannel2
};
// Creates the key comparer
EqualityComparer<Channel> transientEqualityComparerChannel = EqualityComparer<Channel>.Default;
IEqualityComparer<Channel> localComparer = transientEqualityComparerChannel;
// Creates the dictionary
Dictionary<Channel, INotificationChannel> localVal = new Dictionary<Channel, INotificationChannel>(localPairs.Length, localComparer);
// Adds entries to the dictionary
foreach (KeyValuePair<Channel, INotificationChannel> pair in localPairs)
{
localVal[pair.Key] = pair.Value;
}
transientDictionaryChannelINotificationChannel = localVal;
return new NotificationService(transientDictionaryChannelINotificationChannel);
}
}
}
Class diagram:
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
NotificationService --|> INotificationService
DictionaryᐸChannelˏINotificationChannelᐳ --|> IReadOnlyDictionaryᐸChannelˏINotificationChannelᐳ
DictionaryᐸChannelˏINotificationChannelᐳ --|> IDictionaryᐸChannelˏINotificationChannelᐳ
EqualityComparerᐸChannelᐳ --|> IEqualityComparerᐸChannelᐳ
Composition ..> NotificationService : INotificationService NotificationService
KeyValuePairᐸChannelˏINotificationChannelᐳ *-- EmailChannel : EmailChannel
KeyValuePairᐸChannelˏINotificationChannelᐳ *-- SmsChannel : SmsChannel
KeyValuePairᐸChannelˏINotificationChannelᐳ *-- PushChannel : PushChannel
NotificationService *-- DictionaryᐸChannelˏINotificationChannelᐳ : IReadOnlyDictionaryᐸChannelˏINotificationChannelᐳ
DictionaryᐸChannelˏINotificationChannelᐳ *-- ArrayᐸKeyValuePairᐸChannelˏINotificationChannelᐳᐳ : ArrayᐸKeyValuePairᐸChannelˏINotificationChannelᐳᐳ
DictionaryᐸChannelˏINotificationChannelᐳ *-- EqualityComparerᐸChannelᐳ : IEqualityComparerᐸChannelᐳ
ArrayᐸKeyValuePairᐸChannelˏINotificationChannelᐳᐳ *-- KeyValuePairᐸChannelˏINotificationChannelᐳ : "Unique tag #70" KeyValuePairᐸChannelˏINotificationChannelᐳ
ArrayᐸKeyValuePairᐸChannelˏINotificationChannelᐳᐳ *-- KeyValuePairᐸChannelˏINotificationChannelᐳ : "Unique tag #71" KeyValuePairᐸChannelˏINotificationChannelᐳ
ArrayᐸKeyValuePairᐸChannelˏINotificationChannelᐳᐳ *-- KeyValuePairᐸChannelˏINotificationChannelᐳ : "Unique tag #72" KeyValuePairᐸChannelˏINotificationChannelᐳ
class ArrayᐸKeyValuePairᐸChannelˏINotificationChannelᐳᐳ {
<<array>>
}
namespace Pure.DI.UsageTests.BCL.DictionaryScenario {
class Composition {
<<partial>>
+INotificationService NotificationService
}
class EmailChannel {
<<class>>
+EmailChannel()
}
class INotificationService {
<<interface>>
}
class NotificationService {
<<class>>
+NotificationService(IReadOnlyDictionaryᐸChannelˏINotificationChannelᐳ channels)
}
class PushChannel {
<<class>>
+PushChannel()
}
class SmsChannel {
<<class>>
+SmsChannel()
}
}
namespace System.Collections.Generic {
class DictionaryᐸChannelˏINotificationChannelᐳ {
<<class>>
}
class EqualityComparerᐸChannelᐳ {
<<abstract>>
}
class IDictionaryᐸChannelˏINotificationChannelᐳ {
<<interface>>
}
class IEqualityComparerᐸChannelᐳ {
<<interface>>
}
class IReadOnlyDictionaryᐸChannelˏINotificationChannelᐳ {
<<interface>>
}
class KeyValuePairᐸChannelˏINotificationChannelᐳ {
<<struct>>
}
}