<PackageReference Include="Castle.Windsor" Version="6.0.0" />

CallContextLifetimeScope

Provides explicit lifetime scoping within logical path of execution. Used for types with Scoped.
using Castle.Core; using Castle.MicroKernel.Internal; using System; using System.Collections.Concurrent; using System.Globalization; using System.Runtime.Remoting.Messaging; using System.Security; namespace Castle.MicroKernel.Lifestyle.Scoped { public class CallContextLifetimeScope : ILifetimeScope, IDisposable { private static readonly ConcurrentDictionary<Guid, CallContextLifetimeScope> allScopes = new ConcurrentDictionary<Guid, CallContextLifetimeScope>(); private static readonly string callContextKey = "castle.lifetime-scope-" + AppDomain.CurrentDomain.Id.ToString(CultureInfo.InvariantCulture); 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() { using (IUpgradeableLockHolder upgradeableLockHolder = lock.ForReadingUpgradeable()) { if (cache == null) return; upgradeableLockHolder.Upgrade(); cache.Dispose(); cache = null; if (parentScope != null) SetCurrentScope(parentScope); else CallContext.FreeNamedDataSlot(callContextKey); } allScopes.TryRemove(contextId, out CallContextLifetimeScope _); } public Burden GetCachedInstance(ComponentModel model, ScopedInstanceActivationCallback createInstance) { using (IUpgradeableLockHolder upgradeableLockHolder = lock.ForReadingUpgradeable()) { Burden burden = cache[model]; if (burden == null) { upgradeableLockHolder.Upgrade(); burden = createInstance(delegate { }); cache[model] = burden; } return burden; } } [SecuritySafeCritical] private static void SetCurrentScope(CallContextLifetimeScope lifetimeScope) { CallContext.LogicalSetData(callContextKey, (object)lifetimeScope.contextId); } [SecuritySafeCritical] public static CallContextLifetimeScope ObtainCurrentScope() { object obj = CallContext.LogicalGetData(callContextKey); if (!(obj is Guid)) return null; allScopes.TryGetValue((Guid)obj, out CallContextLifetimeScope value); return value; } } }