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; } }