From 7e57c0d28d7f7ccd729a587011c38276bac40e03 Mon Sep 17 00:00:00 2001 From: TheXamlGuy Date: Tue, 14 May 2024 22:49:16 +0100 Subject: [PATCH] WIP to allow mediter handlers to be subscribed to --- Toolkit.Foundation/CommandValueViewModel.cs | 2 +- Toolkit.Foundation/CommandViewModel.cs | 2 +- Toolkit.Foundation/ComponentBuilder.cs | 9 ++- .../ComponentConfigurationViewModel.cs | 6 +- Toolkit.Foundation/DefaultHostBuilder.cs | 6 +- Toolkit.Foundation/HandlerProvider.cs | 26 +++++++++ Toolkit.Foundation/IHandlerProvider.cs | 8 +++ .../{ISubscriber.cs => ISubscription.cs} | 6 +- Toolkit.Foundation/ISubscriptionManager.cs | 10 ---- .../ObservableCollectionViewModel.cs | 8 +-- Toolkit.Foundation/ObservableViewModel.cs | 6 +- Toolkit.Foundation/Publisher.cs | 6 +- Toolkit.Foundation/Subscriber.cs | 11 ---- ...SubscriptionManager.cs => Subscription.cs} | 56 ++++++------------- Toolkit.Foundation/ValueViewModel.cs | 2 +- 15 files changed, 81 insertions(+), 83 deletions(-) create mode 100644 Toolkit.Foundation/HandlerProvider.cs create mode 100644 Toolkit.Foundation/IHandlerProvider.cs rename Toolkit.Foundation/{ISubscriber.cs => ISubscription.cs} (77%) delete mode 100644 Toolkit.Foundation/ISubscriptionManager.cs delete mode 100644 Toolkit.Foundation/Subscriber.cs rename Toolkit.Foundation/{SubscriptionManager.cs => Subscription.cs} (75%) diff --git a/Toolkit.Foundation/CommandValueViewModel.cs b/Toolkit.Foundation/CommandValueViewModel.cs index dd8bbb4..ffe6c82 100644 --- a/Toolkit.Foundation/CommandValueViewModel.cs +++ b/Toolkit.Foundation/CommandValueViewModel.cs @@ -6,7 +6,7 @@ public partial class CommandValueViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) : ValueViewModel(provider, factory, mediator, publisher, subscriber, disposer) { diff --git a/Toolkit.Foundation/CommandViewModel.cs b/Toolkit.Foundation/CommandViewModel.cs index 8727673..7c1e9ee 100644 --- a/Toolkit.Foundation/CommandViewModel.cs +++ b/Toolkit.Foundation/CommandViewModel.cs @@ -6,7 +6,7 @@ public partial class CommandViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) { diff --git a/Toolkit.Foundation/ComponentBuilder.cs b/Toolkit.Foundation/ComponentBuilder.cs index 425e3c9..21e1cbf 100644 --- a/Toolkit.Foundation/ComponentBuilder.cs +++ b/Toolkit.Foundation/ComponentBuilder.cs @@ -27,11 +27,14 @@ public class ComponentBuilder : new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!))); - services.AddScoped(); - services.AddScoped(); services.AddSingleton(); - services.AddTransient(); + services.AddScoped(); + + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Toolkit.Foundation/ComponentConfigurationViewModel.cs b/Toolkit.Foundation/ComponentConfigurationViewModel.cs index 83dc531..888d7c1 100644 --- a/Toolkit.Foundation/ComponentConfigurationViewModel.cs +++ b/Toolkit.Foundation/ComponentConfigurationViewModel.cs @@ -12,7 +12,7 @@ public partial class ComponentConfigurationViewModel(); services.AddScoped(); - services.AddTransient(); - services.AddTransient(); + services.AddTransient(); + services.AddTransient(); + + services.AddTransient(); services.AddTransient(); services.AddTransient(); diff --git a/Toolkit.Foundation/HandlerProvider.cs b/Toolkit.Foundation/HandlerProvider.cs new file mode 100644 index 0000000..404a997 --- /dev/null +++ b/Toolkit.Foundation/HandlerProvider.cs @@ -0,0 +1,26 @@ +namespace Toolkit.Foundation; + +public class HandlerProvider(SubscriptionCollection subscriptions) : + IHandlerProvider +{ + public IEnumerable Get(Type type, + object key) + { + string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}"; + if (subscriptions.TryGetValue(subscriptionKey, out List? subscribers)) + { + foreach (WeakReference weakRef in subscribers.ToArray()) + { + object? target = weakRef.Target; + if (target != null) + { + yield return target; + } + else + { + subscribers.Remove(weakRef); + } + } + } + } +} diff --git a/Toolkit.Foundation/IHandlerProvider.cs b/Toolkit.Foundation/IHandlerProvider.cs new file mode 100644 index 0000000..fa01b63 --- /dev/null +++ b/Toolkit.Foundation/IHandlerProvider.cs @@ -0,0 +1,8 @@ + +namespace Toolkit.Foundation +{ + public interface IHandlerProvider + { + IEnumerable Get(Type type, object key); + } +} \ No newline at end of file diff --git a/Toolkit.Foundation/ISubscriber.cs b/Toolkit.Foundation/ISubscription.cs similarity index 77% rename from Toolkit.Foundation/ISubscriber.cs rename to Toolkit.Foundation/ISubscription.cs index 6948bb2..858c85d 100644 --- a/Toolkit.Foundation/ISubscriber.cs +++ b/Toolkit.Foundation/ISubscription.cs @@ -1,8 +1,8 @@ namespace Toolkit.Foundation; -public interface ISubscriber +public interface ISubscription { - void Remove(object subscriber); - void Add(object subscriber); + + void Remove(object subscriber); } \ No newline at end of file diff --git a/Toolkit.Foundation/ISubscriptionManager.cs b/Toolkit.Foundation/ISubscriptionManager.cs deleted file mode 100644 index c6866b8..0000000 --- a/Toolkit.Foundation/ISubscriptionManager.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Toolkit.Foundation; - -public interface ISubscriptionManager -{ - IEnumerable GetHandlers(Type notificationType, object key); - - void Remove(object subscriber); - - void Add(object subscriber); -} \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableCollectionViewModel.cs b/Toolkit.Foundation/ObservableCollectionViewModel.cs index 00f06c8..7706ab7 100644 --- a/Toolkit.Foundation/ObservableCollectionViewModel.cs +++ b/Toolkit.Foundation/ObservableCollectionViewModel.cs @@ -41,7 +41,7 @@ public partial class ObservableCollectionViewModel : IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) { Provider = provider; @@ -59,7 +59,7 @@ public partial class ObservableCollectionViewModel : IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer, IEnumerable items) { @@ -459,7 +459,7 @@ public partial class ObservableCollectionViewModel(IServiceP IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, IDisposer disposer) : ObservableCollectionViewModel(provider, factory, mediator, publisher, subscriber, disposer) + ISubscription subscriber, IDisposer disposer) : ObservableCollectionViewModel(provider, factory, mediator, publisher, subscriber, disposer) where TViewModel : notnull { [ObservableProperty] @@ -470,6 +470,6 @@ public class ObservableCollectionViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) : ObservableCollectionViewModel(provider, factory, mediator, publisher, subscriber, disposer); \ No newline at end of file diff --git a/Toolkit.Foundation/ObservableViewModel.cs b/Toolkit.Foundation/ObservableViewModel.cs index 22a1c16..35aefce 100644 --- a/Toolkit.Foundation/ObservableViewModel.cs +++ b/Toolkit.Foundation/ObservableViewModel.cs @@ -19,7 +19,7 @@ public partial class ObservableViewModel : IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) { Provider = provider; @@ -80,7 +80,7 @@ public partial class ObservableViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) where TValue : notnull { @@ -92,7 +92,7 @@ public partial class ObservableViewModel(IServiceProvider provider IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer, TValue? value = null) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) where TValue : class diff --git a/Toolkit.Foundation/Publisher.cs b/Toolkit.Foundation/Publisher.cs index 26ff1d5..ccaa823 100644 --- a/Toolkit.Foundation/Publisher.cs +++ b/Toolkit.Foundation/Publisher.cs @@ -3,7 +3,7 @@ using System.Reflection; namespace Toolkit.Foundation; -public class Publisher(ISubscriptionManager subscriptionManager, +public class Publisher(IHandlerProvider handlerProvider, IServiceProvider provider, IDispatcher dispatcher) : IPublisher @@ -29,8 +29,8 @@ public class Publisher(ISubscriptionManager subscriptionManager, List handlers = provider.GetServices(typeof(NotificationHandlerWrapper<>) .MakeGenericType(notificationType)).ToList(); - foreach (object? handler in subscriptionManager - .GetHandlers(notificationType, key!)) + foreach (object? handler in handlerProvider + .Get(notificationType, key!)) { handlers.Add(handler); } diff --git a/Toolkit.Foundation/Subscriber.cs b/Toolkit.Foundation/Subscriber.cs deleted file mode 100644 index 83898a2..0000000 --- a/Toolkit.Foundation/Subscriber.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Toolkit.Foundation; - -public class Subscriber(ISubscriptionManager subscriptionManager) : - ISubscriber -{ - public void Remove(object subscriber) => - subscriptionManager.Remove(subscriber); - - public void Add(object subscriber) => - subscriptionManager.Add(subscriber); -} \ No newline at end of file diff --git a/Toolkit.Foundation/SubscriptionManager.cs b/Toolkit.Foundation/Subscription.cs similarity index 75% rename from Toolkit.Foundation/SubscriptionManager.cs rename to Toolkit.Foundation/Subscription.cs index 62b9216..1905d52 100644 --- a/Toolkit.Foundation/SubscriptionManager.cs +++ b/Toolkit.Foundation/Subscription.cs @@ -2,27 +2,26 @@ namespace Toolkit.Foundation; -public class SubscriptionManager(SubscriptionCollection subscriptions, - IDisposer disposer) : - ISubscriptionManager +public class Subscription(SubscriptionCollection subscriptions, + IDisposer disposer) : + ISubscription { - public IEnumerable GetHandlers(Type notificationType, - object key) + public void Add(object subscriber) { - string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{notificationType}"; - if (subscriptions.TryGetValue(subscriptionKey, out List? subscribers)) + Type handlerType = subscriber.GetType(); + object? key = GetKeyFromHandler(subscriber); + foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) { - foreach (WeakReference weakRef in subscribers.ToArray()) + if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) { - object? target = weakRef.Target; - if (target != null) + string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}"; + subscriptions.AddOrUpdate(subscriptionKey, _ => new List { new(subscriber) }, (_, collection) => { - yield return target; - } - else - { - subscribers.Remove(weakRef); - } + collection.Add(new WeakReference(subscriber)); + return collection; + }); + + disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, argumentType))); } } } @@ -50,27 +49,8 @@ public class SubscriptionManager(SubscriptionCollection subscriptions, } } - public void Add(object subscriber) - { - Type handlerType = subscriber.GetType(); - object? key = GetKeyFromHandler(subscriber); - foreach (Type interfaceType in GetHandlerInterfaces(handlerType)) - { - if (interfaceType.GetGenericArguments().FirstOrDefault() is Type argumentType) - { - 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 void RemoveSubscriber(object subscriber, + private void RemoveSubscriber(object subscriber, Type argumentType) { string subscriptionKey = $"{argumentType}"; @@ -91,11 +71,11 @@ public class SubscriptionManager(SubscriptionCollection subscriptions, } } - private object? GetKeyFromHandler(object handler) => + 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 diff --git a/Toolkit.Foundation/ValueViewModel.cs b/Toolkit.Foundation/ValueViewModel.cs index aed8932..e98c488 100644 --- a/Toolkit.Foundation/ValueViewModel.cs +++ b/Toolkit.Foundation/ValueViewModel.cs @@ -6,7 +6,7 @@ public partial class ValueViewModel(IServiceProvider provider, IServiceFactory factory, IMediator mediator, IPublisher publisher, - ISubscriber subscriber, + ISubscription subscriber, IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) {