You can use the following example to automatically create a session when creating instances of a particular type:
interface IDependency;
class Dependency : IDependency;
interface IService
{
IDependency Dependency { get; }
}
class Service(IDependency dependency) : IService
{
public IDependency Dependency => dependency;
}
// Implements a session
class Program(Func<IService> serviceFactory)
{
public IService CreateService() => serviceFactory();
}
partial class Composition
{
static void Setup() =>
DI.Setup()
// This hint indicates to not generate methods such as Resolve
.Hint(Hint.Resolve, "Off")
.Bind().As(Scoped).To<Dependency>()
// Session composition root
.Root<Service>("SessionRoot", kind: RootKinds.Private)
// Auto scoped
.Bind().To(IService (Composition baseComposition) =>
{
// Creates a session
var session = new Composition(baseComposition);
// Provides a root
return session.SessionRoot;
})
// Program composition root
.Root<Program>("ProgramRoot");
}
var composition = new Composition();
var program = composition.ProgramRoot;
// Creates service in session #1
var service1 = program.CreateService();
// Creates service in session #2
var service2 = program.CreateService();
// Checks that the scoped instances are not identical in different sessions
service1.Dependency.ShouldNotBe(service2.Dependency);
Important
The method Inject()
cannot be used outside of the binding setup.
The following partial class will be generated:
partial class Composition
{
private readonly Composition _root;
private readonly Lock _lock;
private Dependency? _scopedDependency43;
[OrdinalAttribute(256)]
public Composition()
{
_root = this;
_lock = new Lock();
}
internal Composition(Composition parentScope)
{
_root = (parentScope ?? throw new ArgumentNullException(nameof(parentScope)))._root;
_lock = _root._lock;
}
public Program ProgramRoot
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
Func<IService> perBlockFunc1 = new Func<IService>([MethodImpl(MethodImplOptions.AggressiveInlining)] () =>
{
Composition transientComposition3 = this;
IService transientIService2;
Composition localBaseComposition91 = transientComposition3;
// Creates a session
var localSession92= new Composition(localBaseComposition91);
// Provides a root
transientIService2 = localSession92.SessionRoot;
IService localValue90 = transientIService2;
return localValue90;
});
return new Program(perBlockFunc1);
}
}
private Service SessionRoot
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (_scopedDependency43 is null)
{
using (_lock.EnterScope())
{
if (_scopedDependency43 is null)
{
_scopedDependency43 = new Dependency();
}
}
}
return new Service(_scopedDependency43!);
}
}
}
Class diagram:
---
config:
class:
hideEmptyMembersBox: true
---
classDiagram
Dependency --|> IDependency
Composition ..> Program : Program ProgramRoot
Composition ..> Service : Service SessionRoot
Program o-- "PerBlock" FuncᐸIServiceᐳ : FuncᐸIServiceᐳ
Service o-- "Scoped" Dependency : IDependency
FuncᐸIServiceᐳ *-- IService : IService
IService *-- Composition : Composition
namespace Pure.DI.UsageTests.Lifetimes.AutoScopedScenario {
class Composition {
<<partial>>
+Program ProgramRoot
-Service SessionRoot
}
class Dependency {
+Dependency()
}
class IDependency {
<<interface>>
}
class IService {
<<interface>>
}
class Program {
}
class Service {
}
}
namespace System {
class FuncᐸIServiceᐳ {
<<delegate>>
}
}