factory-with-thread-synchronization.md
July 3, 2026 ยท View on GitHub
Factory with thread synchronization
In some cases, initialization of objects requires synchronization of the overall composition flow. This scenario demonstrates how to use factories with thread synchronization to ensure proper initialization order.
using Shouldly;
using Pure.DI;
DI.Setup(nameof(Composition))
.Bind<IMessageBus>().To<IMessageBus>(ctx => {
// Initialization logic requiring synchronization
// of the overall composition flow.
// For example, connecting to a message broker.
lock (ctx.Lock)
{
ctx.Inject(out MessageBus bus);
bus.Connect();
return bus;
}
})
.Bind<INotificationService>().To<NotificationService>()
// Composition root
.Root<INotificationService>("NotificationService");
var composition = new Composition();
var service = composition.NotificationService;
service.Bus.IsConnected.ShouldBeTrue();
interface IMessageBus
{
bool IsConnected { get; }
}
class MessageBus : IMessageBus
{
public bool IsConnected { get; private set; }
public void Connect() => IsConnected = true;
}
interface INotificationService
{
IMessageBus Bus { get; }
}
class NotificationService(IMessageBus bus) : INotificationService
{
public IMessageBus Bus { get; } = bus;
}
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 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
Note
Thread synchronization in factories should be used carefully as it may impact performance. Only use when necessary for correct initialization behavior.
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
public INotificationService NotificationService
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
IMessageBus transientIMessageBus;
// Initialization logic requiring synchronization
// of the overall composition flow.
// For example, connecting to a message broker.
lock (_lock)
{
MessageBus localBus = new MessageBus();
localBus.Connect();
{
transientIMessageBus = localBus;
goto transientIMessageBusFinish;
}
}
transientIMessageBusFinish:
;
return new NotificationService(transientIMessageBus);
}
}
}
Class diagram:
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
NotificationService --|> INotificationService
Composition ..> NotificationService : INotificationService NotificationService
IMessageBus *-- MessageBus : MessageBus
NotificationService *-- IMessageBus : IMessageBus
namespace Pure.DI.UsageTests.Advanced.FactoryWithThreadSynchronizationScenario {
class Composition {
<<partial>>
+INotificationService NotificationService
}
class IMessageBus {
<<interface>>
}
class INotificationService {
<<interface>>
}
class MessageBus {
<<class>>
+MessageBus()
}
class NotificationService {
<<class>>
+NotificationService(IMessageBus bus)
}
}
See also: