<PackageReference Include="Castle.Windsor" Version="5.0.0-beta001" />

CallContextLifetimeScope

Provides explicit lifetime scoping within logical path of execution. Used for types with Scoped.
using Castle.Core; using Castle.Core.Internal; using System; using System.Collections.Concurrent; using System.Security; using System.Threading; namespace Castle.MicroKernel.Lifestyle.Scoped { public class CallContextLifetimeScope : ILifetimeScope, IDisposable { private static readonly ConcurrentDictionary<Guid, CallContextLifetimeScope> allScopes = new ConcurrentDictionary<Guid, CallContextLifetimeScope>(); private static readonly AsyncLocal<Guid> asyncLocal = new AsyncLocal<Guid>(); private readonly Guid contextId = Guid.NewGuid(); private readonly CallContextLifetimeScope parentScope; private readonly Lock lock = Lock.Create(); private ScopeCache cache = new ScopeCache(); public CallContextLifetimeScope() { contextId = Guid.NewGuid(); parentScope = ObtainCurrentScope(); allScopes.TryAdd(contextId, this); SetCurrentScope(this); } [SecuritySafeCritical] public void Dispose() { IUpgradeableLockHolder val = lock.ForReadingUpgradeable(); try { if (cache == null) return; val.Upgrade(); cache.Dispose(); cache = null; if (parentScope != null) SetCurrentScope(parentScope); } finally { ((IDisposable)val)?.Dispose(); } allScopes.TryRemove(contextId, out CallContextLifetimeScope _); } public Burden GetCachedInstance(ComponentModel model, ScopedInstanceActivationCallback createInstance) { IUpgradeableLockHolder val = lock.ForReadingUpgradeable(); try { Burden burden = cache[model]; if (burden == null) { val.Upgrade(); burden = createInstance(delegate { }); cache[model] = burden; } return burden; } finally { ((IDisposable)val)?.Dispose(); } } [SecuritySafeCritical] private static void SetCurrentScope(CallContextLifetimeScope lifetimeScope) { asyncLocal.Value = lifetimeScope.contextId; } [SecuritySafeCritical] public static CallContextLifetimeScope ObtainCurrentScope() { Guid value = asyncLocal.Value; allScopes.TryGetValue(value, out CallContextLifetimeScope value2); return value2; } } }