WIP to allow mediter handlers to be subscribed to

This commit is contained in:
TheXamlGuy
2024-05-14 22:49:16 +01:00
parent 32829d1cf3
commit 7e57c0d28d
15 changed files with 81 additions and 83 deletions
+1 -1
View File
@@ -6,7 +6,7 @@ public partial class CommandValueViewModel<TValue>(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) : IDisposer disposer) :
ValueViewModel<TValue>(provider, factory, mediator, publisher, subscriber, disposer) ValueViewModel<TValue>(provider, factory, mediator, publisher, subscriber, disposer)
{ {
+1 -1
View File
@@ -6,7 +6,7 @@ public partial class CommandViewModel(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) : IDisposer disposer) :
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
{ {
+6 -3
View File
@@ -27,11 +27,14 @@ public class ComponentBuilder :
new ServiceFactory((type, parameters) => new ServiceFactory((type, parameters) =>
ActivatorUtilities.CreateInstance(provider, type, parameters!))); ActivatorUtilities.CreateInstance(provider, type, parameters!)));
services.AddScoped<SubscriptionCollection>();
services.AddScoped<ISubscriptionManager, SubscriptionManager>();
services.AddSingleton<IDisposer, Disposer>(); services.AddSingleton<IDisposer, Disposer>();
services.AddTransient<ISubscriber, Subscriber>(); services.AddScoped<SubscriptionCollection>();
services.AddTransient<IHandlerProvider, HandlerProvider>();
services.AddTransient<ISubscription, Subscription>();
services.AddTransient<ISubscription, Subscription>();
services.AddTransient<IPublisher, Publisher>(); services.AddTransient<IPublisher, Publisher>();
services.AddTransient<IMediator, Mediator>(); services.AddTransient<IMediator, Mediator>();
@@ -12,7 +12,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, THe
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer, IDisposer disposer,
THeader header, THeader header,
TDescription description, TDescription description,
@@ -30,7 +30,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TAc
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer, IDisposer disposer,
TAction action, TAction action,
TConfiguration configuration, TConfiguration configuration,
@@ -72,7 +72,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TDe
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer, IDisposer disposer,
TAction action, TAction action,
TDescription description, TDescription description,
+4 -2
View File
@@ -26,9 +26,11 @@ public class DefaultHostBuilder :
services.AddSingleton<IDisposer, Disposer>(); services.AddSingleton<IDisposer, Disposer>();
services.AddScoped<SubscriptionCollection>(); services.AddScoped<SubscriptionCollection>();
services.AddTransient<ISubscriptionManager, SubscriptionManager>();
services.AddTransient<ISubscriber, Subscriber>(); services.AddTransient<IHandlerProvider, HandlerProvider>();
services.AddTransient<ISubscription, Subscription>();
services.AddTransient<ISubscription, Subscription>();
services.AddTransient<IPublisher, Publisher>(); services.AddTransient<IPublisher, Publisher>();
services.AddTransient<IMediator, Mediator>(); services.AddTransient<IMediator, Mediator>();
+26
View File
@@ -0,0 +1,26 @@
namespace Toolkit.Foundation;
public class HandlerProvider(SubscriptionCollection subscriptions) :
IHandlerProvider
{
public IEnumerable<object?> Get(Type type,
object key)
{
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}";
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
{
foreach (WeakReference weakRef in subscribers.ToArray())
{
object? target = weakRef.Target;
if (target != null)
{
yield return target;
}
else
{
subscribers.Remove(weakRef);
}
}
}
}
}
+8
View File
@@ -0,0 +1,8 @@
namespace Toolkit.Foundation
{
public interface IHandlerProvider
{
IEnumerable<object?> Get(Type type, object key);
}
}
@@ -1,8 +1,8 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public interface ISubscriber public interface ISubscription
{ {
void Remove(object subscriber);
void Add(object subscriber); void Add(object subscriber);
void Remove(object subscriber);
} }
@@ -1,10 +0,0 @@
namespace Toolkit.Foundation;
public interface ISubscriptionManager
{
IEnumerable<object?> GetHandlers(Type notificationType, object key);
void Remove(object subscriber);
void Add(object subscriber);
}
@@ -41,7 +41,7 @@ public partial class ObservableCollectionViewModel<TViewModel> :
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) IDisposer disposer)
{ {
Provider = provider; Provider = provider;
@@ -59,7 +59,7 @@ public partial class ObservableCollectionViewModel<TViewModel> :
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer, IDisposer disposer,
IEnumerable<TViewModel> items) IEnumerable<TViewModel> items)
{ {
@@ -459,7 +459,7 @@ public partial class ObservableCollectionViewModel<TValue, TViewModel>(IServiceP
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, IDisposer disposer) : ObservableCollectionViewModel<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer) ISubscription subscriber, IDisposer disposer) : ObservableCollectionViewModel<TViewModel>(provider, factory, mediator, publisher, subscriber, disposer)
where TViewModel : notnull where TViewModel : notnull
{ {
[ObservableProperty] [ObservableProperty]
@@ -470,6 +470,6 @@ public class ObservableCollectionViewModel(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) : IDisposer disposer) :
ObservableCollectionViewModel<IDisposable>(provider, factory, mediator, publisher, subscriber, disposer); ObservableCollectionViewModel<IDisposable>(provider, factory, mediator, publisher, subscriber, disposer);
+3 -3
View File
@@ -19,7 +19,7 @@ public partial class ObservableViewModel :
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) IDisposer disposer)
{ {
Provider = provider; Provider = provider;
@@ -80,7 +80,7 @@ public partial class ObservableViewModel<TValue>(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) IDisposer disposer) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
where TValue : notnull where TValue : notnull
{ {
@@ -92,7 +92,7 @@ public partial class ObservableViewModel<TKey, TValue>(IServiceProvider provider
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer, IDisposer disposer,
TValue? value = null) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) TValue? value = null) : ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
where TValue : class where TValue : class
+3 -3
View File
@@ -3,7 +3,7 @@ using System.Reflection;
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public class Publisher(ISubscriptionManager subscriptionManager, public class Publisher(IHandlerProvider handlerProvider,
IServiceProvider provider, IServiceProvider provider,
IDispatcher dispatcher) : IDispatcher dispatcher) :
IPublisher IPublisher
@@ -29,8 +29,8 @@ public class Publisher(ISubscriptionManager subscriptionManager,
List<object?> handlers = provider.GetServices(typeof(NotificationHandlerWrapper<>) List<object?> handlers = provider.GetServices(typeof(NotificationHandlerWrapper<>)
.MakeGenericType(notificationType)).ToList(); .MakeGenericType(notificationType)).ToList();
foreach (object? handler in subscriptionManager foreach (object? handler in handlerProvider
.GetHandlers(notificationType, key!)) .Get(notificationType, key!))
{ {
handlers.Add(handler); handlers.Add(handler);
} }
-11
View File
@@ -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);
}
@@ -2,27 +2,26 @@
namespace Toolkit.Foundation; namespace Toolkit.Foundation;
public class SubscriptionManager(SubscriptionCollection subscriptions, public class Subscription(SubscriptionCollection subscriptions,
IDisposer disposer) : IDisposer disposer) :
ISubscriptionManager ISubscription
{ {
public IEnumerable<object?> GetHandlers(Type notificationType, public void Add(object subscriber)
object key)
{ {
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{notificationType}"; Type handlerType = subscriber.GetType();
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers)) 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; string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{argumentType}";
if (target != null) subscriptions.AddOrUpdate(subscriptionKey, _ => new List<WeakReference> { new(subscriber) }, (_, collection) =>
{ {
yield return target; collection.Add(new WeakReference(subscriber));
} return collection;
else });
{
subscribers.Remove(weakRef); disposer.Add(subscriber, Disposable.Create(() => RemoveSubscriber(subscriber, argumentType)));
}
} }
} }
} }
@@ -50,25 +49,6 @@ 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<WeakReference> { 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) Type argumentType)
+1 -1
View File
@@ -6,7 +6,7 @@ public partial class ValueViewModel<TValue>(IServiceProvider provider,
IServiceFactory factory, IServiceFactory factory,
IMediator mediator, IMediator mediator,
IPublisher publisher, IPublisher publisher,
ISubscriber subscriber, ISubscription subscriber,
IDisposer disposer) : IDisposer disposer) :
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer) ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
{ {