fixed a bunch of isses with keyed handlers
This commit is contained in:
@@ -147,23 +147,23 @@ public class FrameHandler :
|
|||||||
};
|
};
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args.Parameters.TryGetValue("IsBackStackEnabled", out object? isBackStackEnabled))
|
if (args.Parameters.TryGetValue("IsBackStackEnabled", out object? isBackStackEnabled))
|
||||||
|
{
|
||||||
|
if (isBackStackEnabled is bool value)
|
||||||
{
|
{
|
||||||
if (isBackStackEnabled is bool value)
|
navigationOptions.IsNavigationStackEnabled = value;
|
||||||
{
|
|
||||||
navigationOptions.IsNavigationStackEnabled = value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (args.Parameters.TryGetValue("ClearBackStack", out object? clearBackStack))
|
if (args.Parameters.TryGetValue("ClearBackStack", out object? clearBackStack))
|
||||||
|
{
|
||||||
|
if (clearBackStack is bool value)
|
||||||
{
|
{
|
||||||
if (clearBackStack is bool value)
|
if (value)
|
||||||
{
|
{
|
||||||
if (value)
|
postNavigateActions.Add(() => CleanUp());
|
||||||
{
|
|
||||||
postNavigateActions.Add(() => CleanUp());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,7 @@ public class ComponentBuilder :
|
|||||||
services.AddScoped<IComponentHost, ComponentHost>();
|
services.AddScoped<IComponentHost, ComponentHost>();
|
||||||
|
|
||||||
services.AddScoped<IServiceFactory>(provider =>
|
services.AddScoped<IServiceFactory>(provider =>
|
||||||
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type,
|
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!)));
|
||||||
parameters?.Where(x => x is not null).ToArray()!)));
|
|
||||||
|
|
||||||
services.AddSingleton<IDisposer, Disposer>();
|
services.AddSingleton<IDisposer, Disposer>();
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,7 @@ public class DefaultHostBuilder :
|
|||||||
.ConfigureServices((context, services) =>
|
.ConfigureServices((context, services) =>
|
||||||
{
|
{
|
||||||
services.AddScoped<IServiceFactory>(provider =>
|
services.AddScoped<IServiceFactory>(provider =>
|
||||||
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type,
|
new ServiceFactory((type, parameters) => ActivatorUtilities.CreateInstance(provider, type, parameters!)));
|
||||||
parameters?.Where(x => x is not null).ToArray()!)));
|
|
||||||
|
|
||||||
services.AddSingleton<IComponentHostCollection,
|
services.AddSingleton<IComponentHostCollection,
|
||||||
ComponentHostCollection>();
|
ComponentHostCollection>();
|
||||||
|
|||||||
@@ -3,12 +3,10 @@
|
|||||||
public class HandlerProvider(SubscriptionCollection subscriptions) :
|
public class HandlerProvider(SubscriptionCollection subscriptions) :
|
||||||
IHandlerProvider
|
IHandlerProvider
|
||||||
{
|
{
|
||||||
public IEnumerable<object?> Get(Type type,
|
public IEnumerable<object?> Get(object key)
|
||||||
object? key = null)
|
|
||||||
{
|
{
|
||||||
var d = subscriptions;
|
var d = subscriptions;
|
||||||
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}";
|
if (subscriptions.TryGetValue(key, out List<WeakReference>? subscribers))
|
||||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
|
|
||||||
{
|
{
|
||||||
foreach (WeakReference weakRef in subscribers.ToArray())
|
foreach (WeakReference weakRef in subscribers.ToArray())
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,5 @@
|
|||||||
|
|
||||||
public interface IHandlerProvider
|
public interface IHandlerProvider
|
||||||
{
|
{
|
||||||
IEnumerable<object?> Get(Type type,
|
IEnumerable<object?> Get(object key);
|
||||||
object? key = null);
|
|
||||||
}
|
}
|
||||||
@@ -49,38 +49,18 @@ public static class IServiceCollectionExtensions
|
|||||||
contract.GetGenericArguments() is { Length: 1 } notificationHandlerArguments)
|
contract.GetGenericArguments() is { Length: 1 } notificationHandlerArguments)
|
||||||
{
|
{
|
||||||
Type notificationType = notificationHandlerArguments[0];
|
Type notificationType = notificationHandlerArguments[0];
|
||||||
|
Type wrapperType = typeof(NotificationHandlerWrapper<>).MakeGenericType(notificationType);
|
||||||
|
|
||||||
Type wrapperType = typeof(NotificationHandlerWrapper<>)
|
string actualKey = $"{(key is not null ? $"{key}:" : "")}{notificationType}";
|
||||||
.MakeGenericType(notificationType);
|
|
||||||
|
|
||||||
if (key is not null)
|
services.Add(new ServiceDescriptor(typeof(INotificationHandler<>)
|
||||||
{
|
.MakeGenericType(notificationType), actualKey, typeof(THandler), lifetime));
|
||||||
services.Add(new ServiceDescriptor(typeof(INotificationHandler<>)
|
|
||||||
.MakeGenericType(notificationType), key, typeof(THandler), lifetime));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.Add(new ServiceDescriptor(typeof(INotificationHandler<>)
|
|
||||||
.MakeGenericType(notificationType), typeof(THandler), lifetime));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
services.Add(new ServiceDescriptor(wrapperType, actualKey, (provider, registeredKey) =>
|
||||||
if (key is not null)
|
|
||||||
{
|
|
||||||
services.Add(new ServiceDescriptor(wrapperType, key, (provider, key) =>
|
|
||||||
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
||||||
provider.GetRequiredKeyedService(typeof(INotificationHandler<>).MakeGenericType(notificationType), key),
|
provider.GetRequiredKeyedService(typeof(INotificationHandler<>).MakeGenericType(notificationType), registeredKey),
|
||||||
provider.GetServices(typeof(IPipelineBehaviour<>)
|
provider.GetServices(typeof(IPipelineBehaviour<>)
|
||||||
.MakeGenericType(notificationType)))!, lifetime));
|
.MakeGenericType(notificationType)))!, lifetime));
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.Add(new ServiceDescriptor(wrapperType, provider =>
|
|
||||||
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
|
||||||
provider.GetRequiredService(typeof(INotificationHandler<>).MakeGenericType(notificationType)),
|
|
||||||
provider.GetServices(typeof(IPipelineBehaviour<>)
|
|
||||||
.MakeGenericType(notificationType)))!, lifetime));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contract.Name == typeof(IHandler<,>).Name &&
|
if (contract.Name == typeof(IHandler<,>).Name &&
|
||||||
@@ -89,36 +69,17 @@ public static class IServiceCollectionExtensions
|
|||||||
Type requestType = handlerArguments[0];
|
Type requestType = handlerArguments[0];
|
||||||
Type responseType = handlerArguments[1];
|
Type responseType = handlerArguments[1];
|
||||||
|
|
||||||
Type wrapperType = typeof(HandlerWrapper<,>)
|
Type wrapperType = typeof(HandlerWrapper<,>).MakeGenericType(requestType, responseType);
|
||||||
.MakeGenericType(requestType, responseType);
|
string actualKey = $"{(key is not null ? $"{key}:" : "")}{wrapperType}";
|
||||||
|
|
||||||
if (key is not null)
|
services.Add(new ServiceDescriptor(typeof(THandler), actualKey,
|
||||||
{
|
typeof(THandler), lifetime));
|
||||||
services.Add(new ServiceDescriptor(typeof(THandler), key,
|
|
||||||
typeof(THandler), lifetime));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.Add(new ServiceDescriptor(typeof(THandler),
|
|
||||||
typeof(THandler), lifetime));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (key is not null)
|
services.Add(new ServiceDescriptor(wrapperType, actualKey, (provider, actualKey) =>
|
||||||
{
|
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
||||||
services.Add(new ServiceDescriptor(wrapperType, key, (provider, key) =>
|
provider.GetRequiredKeyedService<THandler>(actualKey),
|
||||||
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
provider.GetServices(typeof(IPipelineBehaviour<,>)
|
||||||
provider.GetRequiredKeyedService<THandler>(key),
|
.MakeGenericType(requestType, responseType)))!, lifetime));
|
||||||
provider.GetServices(typeof(IPipelineBehaviour<,>)
|
|
||||||
.MakeGenericType(requestType, responseType)))!, lifetime));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
services.Add(new ServiceDescriptor(wrapperType, provider =>
|
|
||||||
provider.GetService<IServiceFactory>()?.Create(wrapperType,
|
|
||||||
provider.GetRequiredService<THandler>(),
|
|
||||||
provider.GetServices(typeof(IPipelineBehaviour<,>)
|
|
||||||
.MakeGenericType(requestType, responseType)))!, lifetime));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,12 +13,15 @@ public class Mediator(IHandlerProvider handlerProvider,
|
|||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
where TMessage : notnull
|
where TMessage : notnull
|
||||||
{
|
{
|
||||||
List<object?> handlers = GetHandlers<TMessage, TResponse>(message, key);
|
Type messageType = message.GetType();
|
||||||
|
Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(messageType, typeof(TResponse));
|
||||||
|
key = $"{(key is not null ? $"{key}:" : "")}{handlerType}";
|
||||||
|
|
||||||
|
List<object?> handlers = GetHandlers(message, handlerType, key);
|
||||||
foreach (object? handler in handlers)
|
foreach (object? handler in handlers)
|
||||||
{
|
{
|
||||||
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]);
|
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]);
|
||||||
if (handleMethod != null)
|
if (handleMethod is not null)
|
||||||
{
|
{
|
||||||
return await (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
return await (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
||||||
}
|
}
|
||||||
@@ -33,14 +36,16 @@ public class Mediator(IHandlerProvider handlerProvider,
|
|||||||
CancellationToken cancellationToken = default)
|
CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Type messageType = message.GetType();
|
Type messageType = message.GetType();
|
||||||
Type handlerWrapperType = typeof(HandlerWrapper<,>).MakeGenericType(message.GetType(), responseType);
|
Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(message.GetType(), responseType);
|
||||||
|
key = $"{(key is not null ? $"{key}:" : "")}{handlerType}";
|
||||||
List<object?> handlers = GetHandlers(message, handlerWrapperType, key);
|
|
||||||
|
|
||||||
|
List<object?> handlers = GetHandlers(message, handlerType, key);
|
||||||
foreach (object? handler in handlers)
|
foreach (object? handler in handlers)
|
||||||
{
|
{
|
||||||
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [messageType, typeof(CancellationToken)]);
|
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle",
|
||||||
if (handleMethod != null)
|
[messageType, typeof(CancellationToken)]);
|
||||||
|
|
||||||
|
if (handleMethod is not null)
|
||||||
{
|
{
|
||||||
dynamic task = handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
dynamic task = handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
||||||
await task;
|
await task;
|
||||||
@@ -86,44 +91,45 @@ public class Mediator(IHandlerProvider handlerProvider,
|
|||||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Type messageType = message.GetType();
|
Type messageType = message.GetType();
|
||||||
Type handlerWrapperType = typeof(HandlerWrapper<,>).MakeGenericType(message.GetType(), responseType);
|
Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(message.GetType(), responseType);
|
||||||
|
key = $"{(key is not null ? $"{key}:" : "")}{handlerType}";
|
||||||
|
|
||||||
List<object?> handlers = GetHandlers(message, handlerWrapperType, key);
|
List<object?> handlers = GetHandlers(message, handlerType, key);
|
||||||
foreach (object? handler in handlers)
|
foreach (object? handler in handlers)
|
||||||
{
|
{
|
||||||
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [messageType, typeof(CancellationToken)]);
|
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle",
|
||||||
if (handleMethod != null)
|
[messageType, typeof(CancellationToken)]);
|
||||||
|
|
||||||
|
if (handleMethod is not null)
|
||||||
{
|
{
|
||||||
yield return await (Task<object?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
yield return await (Task<object?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async IAsyncEnumerable<TResponse?> HandleManyAsync<TMessage, TResponse>(TMessage message,
|
public async IAsyncEnumerable<TResponse?> HandleManyAsync<TMessage, TResponse>(TMessage message,
|
||||||
object? key = null,
|
object? key = null,
|
||||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||||
where TMessage : notnull
|
where TMessage : notnull
|
||||||
{
|
{
|
||||||
List<object?> handlers = GetHandlers<TMessage, TResponse>(message, key);
|
Type messageType = message.GetType();
|
||||||
|
Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(messageType, typeof(TResponse));
|
||||||
|
key = $"{(key is not null ? $"{key}:" : "")}{handlerType}";
|
||||||
|
|
||||||
|
List<object?> handlers = GetHandlers(message, handlerType, key);
|
||||||
foreach (object? handler in handlers)
|
foreach (object? handler in handlers)
|
||||||
{
|
{
|
||||||
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]);
|
MethodInfo? handleMethod = handler?.GetType().GetMethod("Handle", [message.GetType(), typeof(CancellationToken)]);
|
||||||
if (handleMethod != null)
|
if (handleMethod is not null)
|
||||||
{
|
{
|
||||||
yield return await (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
yield return await (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { message, cancellationToken })!;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<object?> GetHandlers<TMessage, TResponse>(TMessage message, object? key)
|
private List<object?> GetHandlers(object message,
|
||||||
where TMessage : notnull
|
Type handlerWrapperType,
|
||||||
{
|
object? key)
|
||||||
Type messageType = message.GetType();
|
|
||||||
Type handlerWrapperType = typeof(HandlerWrapper<,>).MakeGenericType(messageType, typeof(TResponse));
|
|
||||||
|
|
||||||
return GetHandlers(message, handlerWrapperType, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<object?> GetHandlers(object message, Type handlerWrapperType, object? key)
|
|
||||||
{
|
{
|
||||||
Type messageType = message.GetType();
|
Type messageType = message.GetType();
|
||||||
Dictionary<Type, List<object?>> handlers = [];
|
Dictionary<Type, List<object?>> handlers = [];
|
||||||
@@ -145,11 +151,11 @@ public class Mediator(IHandlerProvider handlerProvider,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IEnumerable<object?> keyedServices = key != null ? provider.GetKeyedServices(handlerWrapperType, key) :
|
IEnumerable<object?> keyedServices = key is not null ? provider.GetKeyedServices(handlerWrapperType, key) :
|
||||||
provider.GetServices(handlerWrapperType);
|
provider.GetServices(handlerWrapperType);
|
||||||
AddHandlers(keyedServices);
|
AddHandlers(keyedServices);
|
||||||
|
|
||||||
IEnumerable<object?> additionalHandlers = handlerProvider.Get(messageType, key);
|
IEnumerable<object?> additionalHandlers = handlerProvider.Get(key);
|
||||||
AddHandlers(additionalHandlers);
|
AddHandlers(additionalHandlers);
|
||||||
|
|
||||||
return handlers.SelectMany(entry => entry.Value).ToList();
|
return handlers.SelectMany(entry => entry.Value).ToList();
|
||||||
|
|||||||
@@ -8,31 +8,31 @@ public class NavigateHandler(NamedComponent scope,
|
|||||||
{
|
{
|
||||||
public Task Handle(NavigateEventArgs args)
|
public Task Handle(NavigateEventArgs args)
|
||||||
{
|
{
|
||||||
INavigation? navigationScope = null;
|
INavigation? navigation = null;
|
||||||
if (args.Scope is "self" || args.Scope is "new")
|
if (args.Scope is "self" || args.Scope is "new")
|
||||||
{
|
{
|
||||||
if (args.Sender is IServiceProviderRequired requireServiceProvider)
|
if (args.Sender is IServiceProviderRequired requireServiceProvider)
|
||||||
{
|
{
|
||||||
if (args.Scope is "self")
|
if (args.Scope is "self")
|
||||||
{
|
{
|
||||||
navigationScope = requireServiceProvider.Provider.GetRequiredService<INavigation>();
|
navigation = requireServiceProvider.Provider.GetRequiredService<INavigation>();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (args.Scope is "new")
|
if (args.Scope is "new")
|
||||||
{
|
{
|
||||||
IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope();
|
IServiceScope serviceScope = requireServiceProvider.Provider.CreateScope();
|
||||||
navigationScope = serviceScope.ServiceProvider.GetRequiredService<INavigation>();
|
navigation = serviceScope.ServiceProvider.GetRequiredService<INavigation>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (navigationScope is null)
|
if (navigation is null)
|
||||||
{
|
{
|
||||||
ComponentScopeDescriptor? descriptor = componentScopeProvider.Get(args.Scope ?? scope.Name);
|
ComponentScopeDescriptor? descriptor = componentScopeProvider.Get(args.Scope ?? scope.Name);
|
||||||
navigationScope = descriptor?.Services?.GetRequiredService<INavigation>();
|
navigation = descriptor?.Services?.GetRequiredService<INavigation>();
|
||||||
}
|
}
|
||||||
|
|
||||||
navigationScope?.Navigate(args.Route, args.Sender,
|
navigation?.Navigate(args.Route, args.Sender,
|
||||||
args.Region, args.Navigated, args.Parameters);
|
args.Region, args.Navigated, args.Parameters);
|
||||||
|
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
|
|||||||
@@ -30,10 +30,15 @@ public class Publisher(IHandlerProvider handlerProvider,
|
|||||||
Type handlerType = typeof(NotificationHandlerWrapper<>)
|
Type handlerType = typeof(NotificationHandlerWrapper<>)
|
||||||
.MakeGenericType(notificationType);
|
.MakeGenericType(notificationType);
|
||||||
|
|
||||||
List<object?> handlers = key is not null ? serviceProvider.GetKeyedServices(handlerType, key).ToList() :
|
key = $"{(key is not null ? $"{key}:" : "")}{notificationType}";
|
||||||
serviceProvider.GetServices(handlerType).ToList();
|
|
||||||
|
|
||||||
foreach (object? handler in handlerProvider.Get(notificationType, key))
|
List<object?> handlers = [];
|
||||||
|
foreach (object? handler in handlerProvider.Get(key))
|
||||||
|
{
|
||||||
|
handlers.Add(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (object? handler in serviceProvider.GetKeyedServices(handlerType, key))
|
||||||
{
|
{
|
||||||
handlers.Add(handler);
|
handlers.Add(handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using Avalonia.Controls.Primitives;
|
using Avalonia.Controls.Primitives;
|
||||||
using Avalonia.Xaml.Interactivity;
|
using Avalonia.Xaml.Interactivity;
|
||||||
using Toolkit.Foundation;
|
using Toolkit.Foundation;
|
||||||
|
using Toolkit.UI.Controls.Avalonia;
|
||||||
|
|
||||||
namespace Toolkit.UI.Avalonia;
|
namespace Toolkit.UI.Avalonia;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user