Skip to content

Latest commit

 

History

History
144 lines (122 loc) · 4.22 KB

File metadata and controls

144 lines (122 loc) · 4.22 KB

Tag Unique

Tag.Unique is useful to register a binding with a unique tag. It will not be available through the composition root or Resolve methods directly, but can be injected in compositions as some kind of enumeration. Use this to aggregate multiple implementations without exposing each one as a direct root.

using Shouldly;
using Pure.DI;
using System.Collections.Immutable;

DI.Setup(nameof(Composition))
    .Bind<INotificationChannel<TT>>(Tag.Unique).To<EmailChannel<TT>>()
    .Bind<INotificationChannel<TT>>(Tag.Unique).To<SmsChannel<TT>>()
    .Bind<INotificationService<TT>>().To<NotificationService<TT>>()

    // Composition root
    .Root<INotificationService<string>>("NotificationService");

var composition = new Composition();
var notificationService = composition.NotificationService;
notificationService.Channels.Length.ShouldBe(2);

interface INotificationChannel<T>;

class EmailChannel<T> : INotificationChannel<T>;

class SmsChannel<T> : INotificationChannel<T>;

interface INotificationService<T>
{
    ImmutableArray<INotificationChannel<T>> Channels { get; }
}

class NotificationService<T>(IEnumerable<INotificationChannel<T>> channels)
    : INotificationService<T>
{
    public ImmutableArray<INotificationChannel<T>> 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

Limitations: unique-tag bindings are intentionally hidden from direct resolve; document this to avoid confusion in integration code. See also: Tags, Enumerable.

The following partial class will be generated:

partial class Composition
{
  public INotificationService<string> NotificationService
  {
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    get
    {
      [MethodImpl(MethodImplOptions.AggressiveInlining)]
      IEnumerable<INotificationChannel<string>> EnumerationOf_perBlockIEnumerable137()
      {
        yield return new EmailChannel<string>();
        yield return new SmsChannel<string>();
      }

      return new NotificationService<string>(EnumerationOf_perBlockIEnumerable137());
    }
  }
}

Class diagram:

---
 config:
  maxTextSize: 2147483647
  maxEdges: 2147483647
  class:
   hideEmptyMembersBox: true
---
classDiagram
	NotificationServiceᐸStringᐳ --|> INotificationServiceᐸStringᐳ
	EmailChannelᐸStringᐳ --|> INotificationChannelᐸStringᐳ : "Unique tag #45" 
	SmsChannelᐸStringᐳ --|> INotificationChannelᐸStringᐳ : "Unique tag #46" 
	Composition ..> NotificationServiceᐸStringᐳ : INotificationServiceᐸStringᐳ NotificationService
	NotificationServiceᐸStringᐳ o-- "PerBlock" IEnumerableᐸINotificationChannelᐸStringᐳᐳ : IEnumerableᐸINotificationChannelᐸStringᐳᐳ
	IEnumerableᐸINotificationChannelᐸStringᐳᐳ *--  EmailChannelᐸStringᐳ : "Unique tag #45"  INotificationChannelᐸStringᐳ
	IEnumerableᐸINotificationChannelᐸStringᐳᐳ *--  SmsChannelᐸStringᐳ : "Unique tag #46"  INotificationChannelᐸStringᐳ
	namespace Pure.DI.UsageTests.Advanced.TagUniqueScenario {
		class Composition {
		<<partial>>
		+INotificationServiceᐸStringᐳ NotificationService
		}
		class EmailChannelᐸStringᐳ {
				<<class>>
			+EmailChannel()
		}
		class INotificationChannelᐸStringᐳ {
			<<interface>>
		}
		class INotificationServiceᐸStringᐳ {
			<<interface>>
		}
		class NotificationServiceᐸStringᐳ {
				<<class>>
			+NotificationService(IEnumerableᐸINotificationChannelᐸStringᐳᐳ channels)
		}
		class SmsChannelᐸStringᐳ {
				<<class>>
			+SmsChannel()
		}
	}
	namespace System.Collections.Generic {
		class IEnumerableᐸINotificationChannelᐸStringᐳᐳ {
				<<interface>>
		}
	}
Loading