using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.Bind(Tag.Id).To<TT>(_ => (TT)(object)Guid.NewGuid())
.Bind().To<Dependency<TT>>()
// Generic service builder
.Builders<IService<TT, TT2>>("BuildUpGeneric");
var composition = new Composition();
var service1 = composition.BuildUpGeneric(new Service1<Guid, string>());
service1.Id.ShouldNotBe(Guid.Empty);
service1.Dependency.ShouldBeOfType<Dependency<string>>();
var service2 = composition.BuildUpGeneric(new Service2<Guid, int>());
service2.Id.ShouldBe(Guid.Empty);
service2.Dependency.ShouldBeOfType<Dependency<int>>();
interface IDependency<T>;
class Dependency<T> : IDependency<T>;
interface IService<out T, T2>
{
T Id { get; }
IDependency<T2>? Dependency { get; }
}
record Service1<T, T2>: IService<T, T2>
where T: struct
{
public T Id { get; private set; }
[Dependency]
public IDependency<T2>? Dependency { get; set; }
[Dependency]
public void SetId([Tag(Tag.Id)] T id) => Id = id;
}
record Service2<T, T2>: IService<T, T2>
where T: struct
{
public T Id { get; }
[Dependency]
public IDependency<T2>? Dependency { get; set; }
}
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(128)]
public Composition()
{
_root = this;
}
internal Composition(Composition parentScope)
{
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Service2<T1, T5> BuildUpGeneric<T1, T5>(Service2<T1, T5> buildingInstance)
where T1: struct
{
if (buildingInstance is null) throw new ArgumentNullException(nameof(buildingInstance));
Service2<T1, T5> transientService20;
Service2<T1, T5> localBuildingInstance137 = buildingInstance;
localBuildingInstance137.Dependency = new Dependency<T5>();
transientService20 = localBuildingInstance137;
return transientService20;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Service1<T1, T5> BuildUpGeneric<T1, T5>(Service1<T1, T5> buildingInstance)
where T1: struct
{
if (buildingInstance is null) throw new ArgumentNullException(nameof(buildingInstance));
T1 transientTT2 = (T1)(object)Guid.NewGuid();
Service1<T1, T5> transientService10;
Service1<T1, T5> localBuildingInstance138 = buildingInstance;
localBuildingInstance138.Dependency = new Dependency<T5>();
localBuildingInstance138.SetId(transientTT2);
transientService10 = localBuildingInstance138;
return transientService10;
}
}
Class diagram:
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
DependencyᐸT5ᐳ --|> IDependencyᐸT5ᐳ
Composition ..> Service2ᐸT1ˏT5ᐳ : Service2ᐸT1ˏT5ᐳ BuildUpGenericᐸT1ˏT5ᐳ(Pure.DI.UsageTests.Generics.GenericBuildersScenario.Service2<T1, T5> buildingInstance)
Composition ..> Service1ᐸT1ˏT5ᐳ : Service1ᐸT1ˏT5ᐳ BuildUpGenericᐸT1ˏT5ᐳ(Pure.DI.UsageTests.Generics.GenericBuildersScenario.Service1<T1, T5> buildingInstance)
Service2ᐸT1ˏT5ᐳ *-- DependencyᐸT5ᐳ : IDependencyᐸT5ᐳ
Service1ᐸT1ˏT5ᐳ *-- DependencyᐸT5ᐳ : IDependencyᐸT5ᐳ
Service1ᐸT1ˏT5ᐳ *-- T1 : "Id" T1
namespace Pure.DI.UsageTests.Generics.GenericBuildersScenario {
class Composition {
<<partial>>
+Service2ᐸT1ˏT5ᐳ BuildUpGenericᐸT1ˏT5ᐳ(Pure.DI.UsageTests.Generics.GenericBuildersScenario.Service2<T1, T5> buildingInstance)
+Service1ᐸT1ˏT5ᐳ BuildUpGenericᐸT1ˏT5ᐳ(Pure.DI.UsageTests.Generics.GenericBuildersScenario.Service1<T1, T5> buildingInstance)
}
class DependencyᐸT5ᐳ {
+Dependency()
}
class IDependencyᐸT5ᐳ {
<<interface>>
}
class Service1ᐸT1ˏT5ᐳ {
<<record>>
+IDependencyᐸT5ᐳ Dependency
+SetId(T1 id) : Void
}
class Service2ᐸT1ˏT5ᐳ {
<<record>>
+IDependencyᐸT5ᐳ Dependency
}
}