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,
|
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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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>();
|
||||||
|
|||||||
@@ -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;
|
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);
|
||||||
@@ -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,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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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)
|
||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user