Allow the Mediator to be subscribed to and therefore handled
This commit is contained in:
@@ -4,7 +4,7 @@ public class HandlerProvider(SubscriptionCollection subscriptions) :
|
||||
IHandlerProvider
|
||||
{
|
||||
public IEnumerable<object?> Get(Type type,
|
||||
object key)
|
||||
object? key = null)
|
||||
{
|
||||
string subscriptionKey = $"{(key is not null ? $"{key}:" : "")}{type}";
|
||||
if (subscriptions.TryGetValue(subscriptionKey, out List<WeakReference>? subscribers))
|
||||
|
||||
@@ -3,6 +3,7 @@ namespace Toolkit.Foundation
|
||||
{
|
||||
public interface IHandlerProvider
|
||||
{
|
||||
IEnumerable<object?> Get(Type type, object key);
|
||||
IEnumerable<object?> Get(Type type,
|
||||
object? key = null);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,11 @@ namespace Toolkit.Foundation
|
||||
{
|
||||
public interface IMediator
|
||||
{
|
||||
Task<object?> Handle(object message, CancellationToken cancellationToken = default);
|
||||
Task<TResponse?> Handle<TRequest, TResponse>(TRequest request, CancellationToken cancellationToken = default) where TRequest : notnull;
|
||||
Task<object?> Handle(object message,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TResponse?> Handle<TMessage, TResponse>(TMessage message,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TMessage : notnull;
|
||||
}
|
||||
}
|
||||
@@ -1,27 +1,62 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Toolkit.Foundation;
|
||||
|
||||
public class Mediator(IServiceProvider provider) :
|
||||
public class Mediator(IHandlerProvider handlerProvider,
|
||||
IServiceProvider provider) :
|
||||
IMediator
|
||||
{
|
||||
public Task<TResponse?> Handle<TRequest, TResponse>(TRequest request,
|
||||
public async Task<TResponse?> Handle<TMessage, TResponse>(TMessage message,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TRequest : notnull
|
||||
where TMessage : notnull
|
||||
{
|
||||
Type handlerType = typeof(HandlerWrapper<,>).MakeGenericType(request.GetType(),
|
||||
typeof(TResponse));
|
||||
Type messageType = message.GetType();
|
||||
Type handlerWrapperType = typeof(HandlerWrapper<,>).MakeGenericType(messageType, typeof(TResponse));
|
||||
|
||||
if (provider.GetService(handlerType)
|
||||
is object handler)
|
||||
Dictionary<Type, List<object?>> handlers = [];
|
||||
|
||||
foreach (object? service in provider.GetServices(handlerWrapperType))
|
||||
{
|
||||
if (handlerType.GetMethod("Handle") is MethodInfo handleMethod)
|
||||
if (service?.GetType() is Type serviceType)
|
||||
{
|
||||
return (Task<TResponse?>)handleMethod.Invoke(handler, new object[] { request, cancellationToken })!;
|
||||
if (!handlers.TryGetValue(serviceType, out List<object?>? handlerList))
|
||||
{
|
||||
handlerList = [];
|
||||
handlers.Add(serviceType, handlerList);
|
||||
}
|
||||
|
||||
handlerList.Add(service);
|
||||
}
|
||||
}
|
||||
|
||||
return Task.FromResult<TResponse?>(default);
|
||||
foreach (object? handler in handlerProvider.Get(messageType))
|
||||
{
|
||||
if (handler is not null)
|
||||
{
|
||||
Type handlerType = handler.GetType();
|
||||
if (!handlers.TryGetValue(handlerType, out List<object?>? handlerList))
|
||||
{
|
||||
handlerList = [];
|
||||
handlers.Add(handlerType, handlerList);
|
||||
}
|
||||
handlerList.Add(handler);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Type, List<object?>> handlerEntry in handlers)
|
||||
{
|
||||
foreach (object? handler in handlerEntry.Value)
|
||||
{
|
||||
if (handler?.GetType().GetMethod("Handle") is MethodInfo handleMethod)
|
||||
{
|
||||
return await (Task<TResponse?>)handleMethod.Invoke(handler,
|
||||
new object[] { message, cancellationToken })!;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
public Task<object?> Handle(object message,
|
||||
|
||||
@@ -25,12 +25,11 @@ public class Publisher(IHandlerProvider handlerProvider,
|
||||
object? key = null)
|
||||
{
|
||||
Type notificationType = message.GetType();
|
||||
Type handlerType = typeof(NotificationHandlerWrapper<>)
|
||||
.MakeGenericType(notificationType);
|
||||
|
||||
List<object?> handlers = provider.GetServices(typeof(NotificationHandlerWrapper<>)
|
||||
.MakeGenericType(notificationType)).ToList();
|
||||
|
||||
foreach (object? handler in handlerProvider
|
||||
.Get(notificationType, key!))
|
||||
List<object?> handlers = provider.GetServices(handlerType).ToList();
|
||||
foreach (object? handler in handlerProvider.Get(notificationType, key))
|
||||
{
|
||||
handlers.Add(handler);
|
||||
}
|
||||
@@ -39,8 +38,7 @@ public class Publisher(IHandlerProvider handlerProvider,
|
||||
{
|
||||
if (handler is not null)
|
||||
{
|
||||
Type? handlerType = handler.GetType();
|
||||
MethodInfo? handleMethod = handlerType.GetMethod("Handle",
|
||||
MethodInfo? handleMethod = handler.GetType().GetMethod("Handle",
|
||||
[notificationType]);
|
||||
|
||||
if (handleMethod is not null)
|
||||
|
||||
@@ -76,6 +76,11 @@ public class Subscription(SubscriptionCollection subscriptions,
|
||||
? 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<>));
|
||||
handlerType.GetInterfaces().Where(interfaceType =>
|
||||
{
|
||||
Type? definition = interfaceType.IsGenericType ? interfaceType.GetGenericTypeDefinition() : null;
|
||||
return definition == typeof(INotificationHandler<>) ||
|
||||
definition == typeof(IHandler<>) ||
|
||||
definition == typeof(IHandler<,>);
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user