Allow the Mediator to be subscribed to and therefore handled

This commit is contained in:
TheXamlGuy
2024-05-15 19:28:08 +01:00
parent 7e57c0d28d
commit 8c0436644a
6 changed files with 67 additions and 24 deletions
+1 -1
View File
@@ -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))
+2 -1
View File
@@ -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);
}
}
+6 -2
View File
@@ -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;
}
}
+46 -11
View File
@@ -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,
+5 -7
View File
@@ -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)
+7 -2
View File
@@ -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<,>);
});
}