LifecycledComponentsReleasePolicy
Tracks all components requiring decomission ( RequiresPolicyRelease)
            
                using Castle.Core;
using Castle.Core.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>(ReferenceEqualityComparer<object>.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;
        }
    }
}