diff --git a/Toolkit.Avalonia/ContentControlHandler.cs b/Toolkit.Avalonia/ContentControlHandler.cs index 5b1f0e5..8343f78 100644 --- a/Toolkit.Avalonia/ContentControlHandler.cs +++ b/Toolkit.Avalonia/ContentControlHandler.cs @@ -43,6 +43,11 @@ public class ContentControlHandler : { await deactivated.OnDeactivated(); } + + if (content is IDisposable disposable) + { + disposable.Dispose(); + } } } diff --git a/Toolkit.Avalonia/ContentTemplate.cs b/Toolkit.Avalonia/ContentTemplate.cs index aa4be42..2471d1e 100644 --- a/Toolkit.Avalonia/ContentTemplate.cs +++ b/Toolkit.Avalonia/ContentTemplate.cs @@ -49,14 +49,16 @@ public class ContentTemplate : { await deactivated.OnDeactivated(); } + + if (content is IDisposable disposable) + { + disposable.Dispose(); + } } } control.Loaded += HandleLoaded; control.Unloaded += HandleUnloaded; - - //viewModelContentBinder?.Register(control); - return control; } } diff --git a/Toolkit.Foundation/SubscriptionManager.cs b/Toolkit.Foundation/SubscriptionManager.cs index 2310df9..f51ca3c 100644 --- a/Toolkit.Foundation/SubscriptionManager.cs +++ b/Toolkit.Foundation/SubscriptionManager.cs @@ -1,13 +1,15 @@ -namespace Toolkit.Foundation; +using System.Reactive.Disposables; -public class SubscriptionManager(SubscriptionCollection subscriptions) : +namespace Toolkit.Foundation; + +public class SubscriptionManager(SubscriptionCollection subscriptions, + IDisposer disposer) : ISubscriptionManager { public IEnumerable GetHandlers(Type notificationType, object key) { - var d = subscriptions; - if (subscriptions.TryGetValue($"{(key is not null ? $"{key}:" : "")}{notificationType}", - out List? subscribers)) + string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{notificationType}"; + if (subscriptions.TryGetValue(subscriptionKey, out List? subscribers)) { foreach (WeakReference weakRef in subscribers.ToArray()) { @@ -32,7 +34,8 @@ public class SubscriptionManager(SubscriptionCollection subscriptions) : { if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) { - if (subscriptions.TryGetValue($"{(key is not null ? $"{key}:" : "")}{argumentType}", out List? subscribers)) + string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}"; + if (subscriptions.TryGetValue(subscriptionKey, out List? subscribers)) { for (int i = subscribers.Count - 1; i >= 0; i--) { @@ -54,34 +57,43 @@ public class SubscriptionManager(SubscriptionCollection subscriptions) : { if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) { - if (key is not null) - { - subscriptions.AddOrUpdate($"{key}:{argumentType}", _ => new List { new(subscriber) }, (_, collection) => - { - collection.Add(new WeakReference(subscriber)); - return collection; - }); - - } - - subscriptions.AddOrUpdate($"{argumentType}", _ => new List { new(subscriber) }, (_, collection) => + string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}"; + subscriptions.AddOrUpdate(subscriptionKey, _ => new List { new(subscriber) }, (_, collection) => { collection.Add(new WeakReference(subscriber)); return collection; }); + + disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, argumentType))); } } } - private static object? GetKeyFromHandler(object handler) + private void RemoveSubscriber(object subscriber, Type argumentType) { - return handler.GetAttribute() - is NotificationAttribute attribute - ? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key - : null; + string subscriptionKey = $"{argumentType}"; + if (subscriptions.TryGetValue(subscriptionKey, out List? subscribers)) + { + for (int i = subscribers.Count - 1; i >= 0; i--) + { + if (subscribers[i].Target == subscriber) + { + subscribers.RemoveAt(i); + } + } + + if (subscribers.Count == 0) + { + subscriptions.TryRemove(subscriptionKey, out _); + } + } } - private static IEnumerable GetHandlerInterfaces(Type handlerType) => + private object? GetKeyFromHandler(object handler) => + handler.GetAttribute() is NotificationAttribute attribute + ? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key : null; + + private IEnumerable GetHandlerInterfaces(Type handlerType) => handlerType.GetInterfaces().Where(interfaceType => interfaceType.IsGenericType && - interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)); -} \ No newline at end of file + interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>)); +}