islockrequired.md
July 5, 2026 ยท View on GitHub
IsLockRequired
IsLockRequired indicates whether a lock is required for thread-safe operations in the current context. This property is useful when you need to conditionally synchronize based on thread safety requirements.
Use this when custom factory logic must respect thread-safety semantics of generated code.
using Shouldly;
using Pure.DI;
var composition = new Composition();
var service = composition.Service;
service.Locked.ShouldBeTrue();
var singletonService = composition.SingletonService;
singletonService.Locked.ShouldBeFalse();
interface IService
{
bool Locked { get; }
}
class Service(bool lockRequired) : IService
{
public bool Locked => lockRequired;
}
partial class Composition
{
private void Setup() =>
DI.Setup(nameof(Composition))
.Hint(Hint.ThreadSafe, "On")
.Bind().To(ctx =>
{
// In a thread-safe context, IsLockRequired is true
// Use it to conditionally lock the context
if (ctx.IsLockRequired)
{
lock (ctx.Lock)
{
return new Service(ctx.IsLockRequired);
}
}
return new Service(ctx.IsLockRequired);
})
.Bind(Tag.Single).As(Lifetime.Singleton).To((IService service) => service)
.Root<IService>(nameof(Service))
.Root<IService>(nameof(SingletonService), Tag.Single);
}
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
Limitations: avoid adding business logic inside lock-aware factories; use it only for synchronization concerns. See also: ThreadSafe hint, Factory.
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 IService? _singletonCompositionWithGenericRootsAndArgsInOtherProject;
public IService Service
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
Service transientService;
// In a thread-safe context, IsLockRequired is true
// Use it to conditionally lock the context
if (true)
{
lock (_lock)
{
{
transientService = new Service(true);
goto transientServiceFinish;
}
}
}
transientService = new Service(true);
transientServiceFinish:
;
return transientService;
}
}
public IService SingletonService
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (_singletonCompositionWithGenericRootsAndArgsInOtherProject is null)
lock (_lock)
if (_singletonCompositionWithGenericRootsAndArgsInOtherProject is null)
{
Service transientService;
// In a thread-safe context, IsLockRequired is true
// Use it to conditionally lock the context
if (false)
{
lock (_lock)
{
{
transientService = new Service(false);
goto transientServiceFinish;
}
}
}
transientService = new Service(false);
transientServiceFinish:
;
IService localService = transientService;
_singletonCompositionWithGenericRootsAndArgsInOtherProject = localService;
}
return _singletonCompositionWithGenericRootsAndArgsInOtherProject;
}
}
}
Class diagram:
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
Service --|> IService
Composition ..> IService : IService SingletonService
Composition ..> Service : IService Service
IService *-- Service : IService
namespace Pure.DI.UsageTests.Advanced.IsLockRequiredScenario {
class Composition {
<<partial>>
+IService Service
+IService SingletonService
}
class IService {
<<interface>>
}
class Service {
<<class>>
}
}
See also: