Demonstrates how to create factories with lifetime-specific bindings, providing a concise way to define factories with proper lifetime semantics.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.Transient(Guid.NewGuid)
.Transient(() => DateTime.Today, "today")
// Injects FileLogger and DateTime instances
// and performs further initialization logic
// defined in the lambda function to set up the log file name
.Singleton<FileLogger, DateTime, IFileLogger>((
logger,
[Tag("today")] date) => {
logger.Init($"app-{date:yyyy-MM-dd}.log");
return logger;
})
.Transient<OrderProcessingService>()
// Composition root
.Root<IOrderProcessingService>("OrderService");
var composition = new Composition();
var service = composition.OrderService;
service.Logger.FileName.ShouldBe($"app-{DateTime.Today:yyyy-MM-dd}.log");
interface IFileLogger
{
string FileName { get; }
void Log(string message);
}
class FileLogger(Func<Guid> idFactory) : IFileLogger
{
public string FileName { get; private set; } = "";
public void Init(string fileName) => FileName = fileName;
public void Log(string message)
{
var id = idFactory();
// Write to file
}
}
interface IOrderProcessingService
{
IFileLogger Logger { get; }
}
class OrderProcessingService(IFileLogger logger) : IOrderProcessingService
{
public IFileLogger Logger { get; } = logger;
}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
Lifetime-specific factories combine the convenience of simplified syntax with explicit lifetime control for optimal performance and correctness.
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
private IFileLogger? _singletonIFileLogger64;
public IOrderProcessingService OrderService
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (_singletonIFileLogger64 is null)
lock (_lock)
if (_singletonIFileLogger64 is null)
{
Func<Guid> perBlockFunc354 = new Func<Guid>(
[MethodImpl(MethodImplOptions.AggressiveInlining)]
() =>
{
Guid transientGuid355 = Guid.NewGuid();
return transientGuid355;
});
FileLogger localLogger5 = new FileLogger(perBlockFunc354);
DateTime transientDateTime353 = DateTime.Today;
DateTime localDate1 = transientDateTime353;
localLogger5.Init($"app-{localDate1:yyyy-MM-dd}.log");
_singletonIFileLogger64 = localLogger5;
}
return new OrderProcessingService(_singletonIFileLogger64);
}
}
}Class diagram:
---
config:
maxTextSize: 2147483647
maxEdges: 2147483647
class:
hideEmptyMembersBox: true
---
classDiagram
Guid --|> IComparable
Guid --|> IComparableᐸGuidᐳ
Guid --|> IEquatableᐸGuidᐳ
Guid --|> IFormattable
Guid --|> IParsableᐸGuidᐳ
Guid --|> ISpanFormattable
Guid --|> ISpanParsableᐸGuidᐳ
Guid --|> IUtf8SpanFormattable
Guid --|> IUtf8SpanParsableᐸGuidᐳ
OrderProcessingService --|> IOrderProcessingService
Composition ..> OrderProcessingService : IOrderProcessingService OrderService
IFileLogger *-- DateTime : "today" DateTime
IFileLogger *-- FileLogger : FileLogger
OrderProcessingService o-- "Singleton" IFileLogger : IFileLogger
FileLogger o-- "PerBlock" FuncᐸGuidᐳ : FuncᐸGuidᐳ
FuncᐸGuidᐳ *-- Guid : Guid
namespace Pure.DI.UsageTests.Basics.SimplifiedLifetimeFactoryScenario {
class Composition {
<<partial>>
+IOrderProcessingService OrderService
}
class FileLogger {
<<class>>
+FileLogger(FuncᐸGuidᐳ idFactory)
}
class IFileLogger {
<<interface>>
}
class IOrderProcessingService {
<<interface>>
}
class OrderProcessingService {
<<class>>
+OrderProcessingService(IFileLogger logger)
}
}
namespace System {
class DateTime {
<<struct>>
}
class FuncᐸGuidᐳ {
<<delegate>>
}
class Guid {
<<struct>>
}
class IComparable {
<<interface>>
}
class IComparableᐸGuidᐳ {
<<interface>>
}
class IEquatableᐸGuidᐳ {
<<interface>>
}
class IFormattable {
<<interface>>
}
class IParsableᐸGuidᐳ {
<<interface>>
}
class ISpanFormattable {
<<interface>>
}
class ISpanParsableᐸGuidᐳ {
<<interface>>
}
class IUtf8SpanFormattable {
<<interface>>
}
class IUtf8SpanParsableᐸGuidᐳ {
<<interface>>
}
}