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

LifecycledComponentsReleasePolicy

Tracks all components requiring decomission ( RequiresPolicyRelease)
using Castle.Core; using Castle.Core.Internal; using Castle.MicroKernel.Internal; using Castle.Windsor.Diagnostics; using System; using System.Collections.Generic; using System.Linq; using System.Security; namespace Castle.MicroKernel.Releasers { [Serializable] public class LifecycledComponentsReleasePolicy : IReleasePolicy, IDisposable { private readonly Dictionary<object, Burden> instance2Burden = new Dictionary<object, Burden>((IEqualityComparer<object>)ReferenceEqualityComparer<object>.get_Instance()); private readonly Lock lock = Lock.Create(); private readonly ITrackedComponentsPerformanceCounter perfCounter; private ITrackedComponentsDiagnostic trackedComponentsDiagnostic; private Burden[] TrackedObjects { get { using (ILockHolder lockHolder = lock.ForReading(false)) { bool lockAcquired = lockHolder.LockAcquired; return instance2Burden.Values.ToArray(); } } } public LifecycledComponentsReleasePolicy(IKernel kernel) : this(GetTrackedComponentsDiagnostic(kernel), null) { } public LifecycledComponentsReleasePolicy(ITrackedComponentsDiagnostic trackedComponentsDiagnostic, ITrackedComponentsPerformanceCounter trackedComponentsPerformanceCounter) { this.trackedComponentsDiagnostic = trackedComponentsDiagnostic; perfCounter = (trackedComponentsPerformanceCounter ?? NullPerformanceCounter.Instance); if (trackedComponentsDiagnostic != null) trackedComponentsDiagnostic.TrackedInstancesRequested += trackedComponentsDiagnostic_TrackedInstancesRequested; } private LifecycledComponentsReleasePolicy(LifecycledComponentsReleasePolicy parent) : this(parent.trackedComponentsDiagnostic, parent.perfCounter) { } public void Dispose() { KeyValuePair<object, Burden>[] source = default(KeyValuePair<object, Burden>[]); using (lock.ForWriting()) { if (trackedComponentsDiagnostic != null) { trackedComponentsDiagnostic.TrackedInstancesRequested -= trackedComponentsDiagnostic_TrackedInstancesRequested; trackedComponentsDiagnostic = null; } source = instance2Burden.ToArray(); instance2Burden.Clear(); } foreach (KeyValuePair<object, Burden> item in source.Reverse()) { item.Value.Released -= OnInstanceReleased; perfCounter.DecrementTrackedInstancesCount(); item.Value.Release(); } } public IReleasePolicy CreateSubPolicy() { return new LifecycledComponentsReleasePolicy(this); } public bool HasTrack(object instance) { if (instance == null) return false; using (lock.ForReading()) return instance2Burden.ContainsKey(instance); } public void Release(object instance) { if (instance != null) { Burden value; using (lock.ForWriting()) { if (!instance2Burden.TryGetValue(instance, out value)) return; } value.Release(); } } public virtual void Track(object instance, Burden burden) { if (!burden.RequiresPolicyRelease) { object arg = burden.Model.CustomLifestyle ?? ((object)burden.Model.LifestyleType); throw new ArgumentException($"""{instance}""{arg}"""); } try { using (lock.ForWriting()) instance2Burden.Add(instance, burden); } catch (ArgumentNullException) { throw; } catch (ArgumentException) { throw HelpfulExceptionsUtil.TrackInstanceCalledMultipleTimes(instance, burden); } burden.Released += OnInstanceReleased; perfCounter.IncrementTrackedInstancesCount(); } private void OnInstanceReleased(Burden burden) { using (lock.ForWriting()) { if (!instance2Burden.Remove(burden.Instance)) return; } burden.Released -= OnInstanceReleased; perfCounter.DecrementTrackedInstancesCount(); } private void trackedComponentsDiagnostic_TrackedInstancesRequested(object sender, TrackedInstancesEventArgs e) { e.AddRange(TrackedObjects); } public static ITrackedComponentsDiagnostic GetTrackedComponentsDiagnostic(IKernel kernel) { return ((IDiagnosticsHost)kernel.GetSubSystem(SubSystemConstants.DiagnosticsKey))?.GetDiagnostic<ITrackedComponentsDiagnostic>(); } [SecuritySafeCritical] public static ITrackedComponentsPerformanceCounter GetTrackedComponentsPerformanceCounter(IPerformanceMetricsFactory perfMetricsFactory) { return NullPerformanceCounter.Instance; } } }