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.
using Shouldly;
using Pure.DI;
using System.Collections.Immutable;
DI.Setup(nameof(Composition))
.Bind<IDependency<TT>>(Tag.Unique).To<AbcDependency<TT>>()
.Bind<IDependency<TT>>(Tag.Unique).To<XyzDependency<TT>>()
.Bind<IService<TT>>().To<Service<TT>>()
// Composition root
.Root<IService<string>>("Root");
var composition = new Composition();
var stringService = composition.Root;
stringService.Dependencies.Length.ShouldBe(2);
interface IDependency<T>;
class AbcDependency<T> : IDependency<T>;
class XyzDependency<T> : IDependency<T>;
interface IService<T>
{
ImmutableArray<IDependency<T>> Dependencies { get; }
}
class Service<T>(IEnumerable<IDependency<T>> dependencies) : IService<T>
{
public ImmutableArray<IDependency<T>> Dependencies { get; }
= [..dependencies];
}
Running this code sample locally
- Make sure you have the .NET SDK 9.0 or later is installed
dotnet --list-sdk
- Create a net9.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
The following partial class will be generated:
partial class Composition
{
private readonly Composition _root;
[OrdinalAttribute(256)]
public Composition()
{
_root = this;
}
internal Composition(Composition parentScope)
{
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
}
public IService<string> Root
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
IEnumerable<IDependency<string>> EnumerationOf_perBlockIEnumerable1()
{
yield return new AbcDependency<string>();
yield return new XyzDependency<string>();
}
IEnumerable<IDependency<string>> perBlockIEnumerable1 = EnumerationOf_perBlockIEnumerable1();
return new Service<string>(perBlockIEnumerable1);
}
}
}
Class diagram:
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
ServiceᐸStringᐳ --|> IServiceᐸStringᐳ
AbcDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : typeof(Pure.DI.UsageTests.Advanced.TagUniqueScenario.AbcDependency<Pure.DI.TT>)
XyzDependencyᐸStringᐳ --|> IDependencyᐸStringᐳ : typeof(Pure.DI.UsageTests.Advanced.TagUniqueScenario.XyzDependency<Pure.DI.TT>)
Composition ..> ServiceᐸStringᐳ : IServiceᐸStringᐳ Root
ServiceᐸStringᐳ o-- "PerBlock" IEnumerableᐸIDependencyᐸStringᐳᐳ : IEnumerableᐸIDependencyᐸStringᐳᐳ
IEnumerableᐸIDependencyᐸStringᐳᐳ *-- AbcDependencyᐸStringᐳ : typeof(Pure.DI.UsageTests.Advanced.TagUniqueScenario.AbcDependency<Pure.DI.TT>) IDependencyᐸStringᐳ
IEnumerableᐸIDependencyᐸStringᐳᐳ *-- XyzDependencyᐸStringᐳ : typeof(Pure.DI.UsageTests.Advanced.TagUniqueScenario.XyzDependency<Pure.DI.TT>) IDependencyᐸStringᐳ
namespace Pure.DI.UsageTests.Advanced.TagUniqueScenario {
class AbcDependencyᐸStringᐳ {
+AbcDependency()
}
class Composition {
<<partial>>
+IServiceᐸStringᐳ Root
}
class IDependencyᐸStringᐳ {
<<interface>>
}
class IServiceᐸStringᐳ {
<<interface>>
}
class ServiceᐸStringᐳ {
+Service(IEnumerableᐸIDependencyᐸStringᐳᐳ dependencies)
}
class XyzDependencyᐸStringᐳ {
+XyzDependency()
}
}
namespace System.Collections.Generic {
class IEnumerableᐸIDependencyᐸStringᐳᐳ {
<<interface>>
}
}