WIP to allow mediter handlers to be subscribed to
This commit is contained in:
@@ -6,7 +6,7 @@ public partial class CommandValueViewModel<TValue>(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ValueViewModel<TValue>(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -27,11 +27,14 @@ public class ComponentBuilder :
|
||||
new ServiceFactory((type, parameters) =>
|
||||
ActivatorUtilities.CreateInstance(provider, type, parameters!)));
|
||||
|
||||
services.AddScoped<SubscriptionCollection>();
|
||||
services.AddScoped<ISubscriptionManager, SubscriptionManager>();
|
||||
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<IMediator, Mediator>();
|
||||
|
||||
@@ -12,7 +12,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, THe
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
THeader header,
|
||||
TDescription description,
|
||||
@@ -30,7 +30,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TAc
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
TAction action,
|
||||
TConfiguration configuration,
|
||||
@@ -72,7 +72,7 @@ public partial class ComponentConfigurationViewModel<TConfiguration, TValue, TDe
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
TAction action,
|
||||
TDescription description,
|
||||
|
||||
@@ -26,9 +26,11 @@ public class DefaultHostBuilder :
|
||||
services.AddSingleton<IDisposer, Disposer>();
|
||||
|
||||
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<IMediator, Mediator>();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
|
||||
namespace Toolkit.Foundation
|
||||
{
|
||||
public interface IHandlerProvider
|
||||
{
|
||||
IEnumerable<object?> Get(Type type, object key);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer)
|
||||
{
|
||||
Provider = provider;
|
||||
@@ -59,7 +59,7 @@ public partial class ObservableCollectionViewModel<TViewModel> :
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer,
|
||||
IEnumerable<TViewModel> items)
|
||||
{
|
||||
@@ -459,7 +459,7 @@ public partial class ObservableCollectionViewModel<TValue, TViewModel>(IServiceP
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
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
|
||||
{
|
||||
[ObservableProperty]
|
||||
@@ -470,6 +470,6 @@ public class ObservableCollectionViewModel(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableCollectionViewModel<IDisposable>(provider, factory, mediator, publisher, subscriber, disposer);
|
||||
@@ -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<TValue>(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<TKey, TValue>(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
|
||||
|
||||
@@ -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<object?> 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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
public class SubscriptionManager(SubscriptionCollection subscriptions,
|
||||
IDisposer disposer) :
|
||||
ISubscriptionManager
|
||||
public class Subscription(SubscriptionCollection subscriptions,
|
||||
IDisposer disposer) :
|
||||
ISubscription
|
||||
{
|
||||
public IEnumerable<object?> GetHandlers(Type notificationType,
|
||||
object key)
|
||||
public void Add(object subscriber)
|
||||
{
|
||||
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{notificationType}";
|
||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? 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<WeakReference> { 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<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)
|
||||
{
|
||||
string subscriptionKey = $"{argumentType}";
|
||||
@@ -91,11 +71,11 @@ public class SubscriptionManager(SubscriptionCollection subscriptions,
|
||||
}
|
||||
}
|
||||
|
||||
private object? GetKeyFromHandler(object handler) =>
|
||||
private object? GetKeyFromHandler(object handler) =>
|
||||
handler.GetAttribute<NotificationAttribute>() is NotificationAttribute attribute
|
||||
? handler.GetPropertyValue(() => attribute.Key) is { } value ? value : attribute.Key : null;
|
||||
|
||||
private IEnumerable<Type> GetHandlerInterfaces(Type handlerType) =>
|
||||
handlerType.GetInterfaces().Where(interfaceType => interfaceType.IsGenericType &&
|
||||
interfaceType.GetGenericTypeDefinition() == typeof(INotificationHandler<>));
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ public partial class ValueViewModel<TValue>(IServiceProvider provider,
|
||||
IServiceFactory factory,
|
||||
IMediator mediator,
|
||||
IPublisher publisher,
|
||||
ISubscriber subscriber,
|
||||
ISubscription subscriber,
|
||||
IDisposer disposer) :
|
||||
ObservableViewModel(provider, factory, mediator, publisher, subscriber, disposer)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user