Demonstrates complex generic root argument scenarios with multiple type parameters and constraints.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
// Defines a generic root argument 'config' of type SourceConfig<T>.
// This allows passing specific configuration when resolving ISource<T>.
.RootArg<SourceConfig<TT>>("config")
.Bind<ISource<TT2>>().To<Source<TT2>>()
// Composition root that creates a source for a specific type.
// The 'GetSource' method will accept 'SourceConfig<T>' as an argument.
.Root<ISource<TT3>>("GetSource");
var composition = new Composition();
// Resolve a source for 'int', passing specific configuration
var source = composition.GetSource<int>(
new SourceConfig<int>(33, "IntSource"));
source.Value.ShouldBe(33);
source.Name.ShouldBe("IntSource");
// Represents configuration for a data source, including a default value
record SourceConfig<T>(T DefaultValue, string SourceName);
interface ISource<out T>
{
T? Value { get; }
string Name { get; }
}
class Source<T> : ISource<T>
{
// The Dependency attribute specifies to perform an injection.
// We use method injection to initialize the source with configuration
// passed from the composition root.
[Dependency]
public void Initialize(SourceConfig<T> config)
{
Value = config.DefaultValue;
Name = config.SourceName;
}
public T? Value { get; private set; }
public string Name { get; private set; } = "";
}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
Complex generic scenarios require careful attention to type constraints and argument order for correct resolution.
The following partial class will be generated:
partial class Composition
{
#if NET9_0_OR_GREATER
private readonly Lock _lock = new Lock();
#else
private readonly Object _lock = new Object();
#endif
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ISource<T> GetSource<T>(SourceConfig<T> config)
{
if (config is null) throw new ArgumentNullException(nameof(config));
var transientSource467 = new Source<T>();
transientSource467.Initialize(config);
return transientSource467;
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
SourceᐸTᐳ --|> ISourceᐸTᐳ
Composition ..> SourceᐸTᐳ : ISourceᐸTᐳ GetSourceᐸTᐳ(Pure.DI.UsageTests.Generics.ComplexGenericRootArgScenario.SourceConfig<T> config)
SourceᐸTᐳ o-- SourceConfigᐸTᐳ : Argument "config"
namespace Pure.DI.UsageTests.Generics.ComplexGenericRootArgScenario {
class Composition {
<<partial>>
+ISourceᐸTᐳ GetSourceᐸTᐳ(Pure.DI.UsageTests.Generics.ComplexGenericRootArgScenario.SourceConfig<T> config)
}
class ISourceᐸTᐳ {
<<interface>>
}
class SourceConfigᐸTᐳ {
<<record>>
}
class SourceᐸTᐳ {
<<class>>
+Source()
+Initialize(SourceConfigᐸTᐳ config) : Void
}
}