using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using Elsa.Mediator.Contracts;
using Elsa.Mediator.Middleware.Command;
using Elsa.Mediator.Middleware.Notification;
using Elsa.Mediator.Models;
namespace Elsa.Mediator.Extensions;
///
/// Contains helper methods for invoking notification handlers.
///
public static class HandlerExtensions
{
///
/// Gets the handle method for a notification handler of the given notification type.
///
/// The notification type.
/// The handle method.
public static MethodInfo GetNotificationHandlerMethod(this Type notificationType)
{
var handlerType = typeof(INotificationHandler<>).MakeGenericType(notificationType);
return handlerType.GetMethod("HandleAsync")!;
}
///
/// Gets the handle method for a command handler of the given command type.
///
/// The command type.
/// The handle method.
public static MethodInfo GetCommandHandlerMethod([DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.Interfaces)] this Type commandType)
{
var commandTypeInterfaces = commandType.GetInterfaces();
var commandTypeInterface = commandTypeInterfaces.FirstOrDefault(x => x.IsGenericType && x.GetGenericTypeDefinition() == typeof(ICommand<>));
var resultType = commandTypeInterface?.GetGenericArguments()[0] ?? typeof(Unit);
var handlerType = typeof(ICommandHandler<,>).MakeGenericType(commandType, resultType);
return handlerType.GetMethod("HandleAsync")!;
}
///
/// Invokes the given handler for the given notification.
///
/// The handler to invoke.
/// The handle method.
/// The notification context containing the notification and cancellation token.
public static Task InvokeAsync(this INotificationHandler handler, MethodBase handleMethod, NotificationContext notificationContext)
{
var notification = notificationContext.Notification;
var cancellationToken = notificationContext.CancellationToken;
return (Task)handleMethod.Invoke(handler, [notification, cancellationToken])!;
}
///
/// Invokes the given handler for the given command.
///
/// The handler to invoke.
/// The handle method.
/// The command to handle.
public static Task InvokeAsync(this ICommandHandler handler, MethodBase handleMethod, CommandContext commandContext)
{
var command = commandContext.Command;
var cancellationToken = commandContext.CancellationToken;
var task = (Task)handleMethod.Invoke(handler, [command, cancellationToken])!;
return task;
}
}