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 Sampledotnet 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 runNote
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> transientDictionary378;
KeyValuePair<Channel, INotificationChannel> transientKeyValuePair381;
EmailChannel localChanel = new EmailChannel();
transientKeyValuePair381 = new KeyValuePair<Channel, INotificationChannel>(Channel.Email, localChanel);
KeyValuePair<Channel, INotificationChannel> transientKeyValuePair382;
SmsChannel localChanel1 = new SmsChannel();
transientKeyValuePair382 = new KeyValuePair<Channel, INotificationChannel>(Channel.Sms, localChanel1);
KeyValuePair<Channel, INotificationChannel> transientKeyValuePair383;
PushChannel localChanel2 = new PushChannel();
transientKeyValuePair383 = new KeyValuePair<Channel, INotificationChannel>(Channel.Push, localChanel2);
KeyValuePair<Channel, INotificationChannel>[] localPairs = new KeyValuePair<Channel, INotificationChannel>[3]
{
transientKeyValuePair381,
transientKeyValuePair382,
transientKeyValuePair383
};
EqualityComparer<Channel> transientEqualityComparer380 = EqualityComparer<Channel>.Default;
IEqualityComparer<Channel> localComparer = transientEqualityComparer380;
Dictionary<Channel, INotificationChannel> localVal = new Dictionary<Channel, INotificationChannel>(localPairs.Length, localComparer);
foreach (KeyValuePair<Channel, INotificationChannel> pair in localPairs)
{
localVal[pair.Key] = pair.Value;
}
transientDictionary378 = localVal;
return new NotificationService(transientDictionary378);
}
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
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 #69" KeyValuePairᐸChannelˏINotificationChannelᐳ
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ᐳ
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>>
}
}