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
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>>
		}
	}