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

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.Diagnostics; using System.Linq; using System.Security; using System.Threading; namespace Castle.MicroKernel.Releasers { [Serializable] public class LifecycledComponentsReleasePolicy : IReleasePolicy, IDisposable { private static int instanceId; 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 { ILockHolder val = lock.ForReading(false); try { val.get_LockAcquired(); return instance2Burden.Values.ToArray(); } finally { ((IDisposable)val)?.Dispose(); } } } 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() { ILockHolder val = lock.ForWriting(); KeyValuePair<object, Burden>[] source = default(KeyValuePair<object, Burden>[]); try { if (trackedComponentsDiagnostic != null) { trackedComponentsDiagnostic.TrackedInstancesRequested -= trackedComponentsDiagnostic_TrackedInstancesRequested; trackedComponentsDiagnostic = null; } source = instance2Burden.ToArray(); instance2Burden.Clear(); } finally { ((IDisposable)val)?.Dispose(); } 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) { ILockHolder val = lock.ForReading(); try { return instance2Burden.ContainsKey(instance); } finally { ((IDisposable)val)?.Dispose(); } } return false; } public void Release(object instance) { if (instance != null) { ILockHolder val = lock.ForWriting(); Burden value; try { if (!instance2Burden.TryGetValue(instance, out value)) return; } finally { ((IDisposable)val)?.Dispose(); } 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 { ILockHolder val = lock.ForWriting(); try { instance2Burden.Add(instance, burden); } finally { ((IDisposable)val)?.Dispose(); } } catch (ArgumentNullException) { throw; } catch (ArgumentException) { throw HelpfulExceptionsUtil.TrackInstanceCalledMultipleTimes(instance, burden); } burden.Released += OnInstanceReleased; perfCounter.IncrementTrackedInstancesCount(); } private void OnInstanceReleased(Burden burden) { ILockHolder val = lock.ForWriting(); try { if (!instance2Burden.Remove(burden.Instance)) return; } finally { ((IDisposable)val)?.Dispose(); } 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) { Process currentProcess = Process.GetCurrentProcess(); string name = $"""{Interlocked.Increment(ref instanceId)}""{currentProcess.ProcessName}""{currentProcess.Id}"""; return perfMetricsFactory.CreateInstancesTrackedByReleasePolicyCounter(name); } } }