| | | 1 | | using Elsa.Mediator.Contracts; |
| | | 2 | | using Elsa.Mediator.Middleware.Request.Contracts; |
| | | 3 | | |
| | | 4 | | namespace Elsa.Mediator.Middleware.Request.Components; |
| | | 5 | | |
| | | 6 | | /// <summary> |
| | | 7 | | /// A middleware component that invokes request handlers. |
| | | 8 | | /// </summary> |
| | 0 | 9 | | public class RequestHandlerInvokerMiddleware( |
| | 0 | 10 | | RequestMiddlewareDelegate next, |
| | 0 | 11 | | IEnumerable<IRequestHandler> requestHandlers) : IRequestMiddleware |
| | | 12 | | { |
| | | 13 | | /// <inheritdoc /> |
| | | 14 | | public async ValueTask InvokeAsync(RequestContext context) |
| | | 15 | | { |
| | | 16 | | |
| | | 17 | | // Find all handlers for the specified request. |
| | 0 | 18 | | var request = context.Request; |
| | 0 | 19 | | var requestType = request.GetType(); |
| | 0 | 20 | | var responseType = context.ResponseType; |
| | 0 | 21 | | var handlerType = typeof(IRequestHandler<,>).MakeGenericType(requestType, responseType); |
| | 0 | 22 | | var handlers = requestHandlers.Where(x => handlerType.IsInstanceOfType(x)).ToArray(); |
| | | 23 | | |
| | 0 | 24 | | if (handlers.Length == 0) |
| | 0 | 25 | | throw new InvalidOperationException($"There is no handler to handle the {requestType.FullName} request"); |
| | | 26 | | |
| | 0 | 27 | | if (handlers.Length > 1) |
| | 0 | 28 | | throw new InvalidOperationException($"Multiple handlers were found to handle the {requestType.FullName} requ |
| | | 29 | | |
| | 0 | 30 | | var handler = handlers.First(); |
| | 0 | 31 | | var handleMethod = handlerType.GetMethod("HandleAsync")!; |
| | 0 | 32 | | var cancellationToken = context.CancellationToken; |
| | 0 | 33 | | var task = (Task)handleMethod.Invoke(handler, [request, cancellationToken])!; |
| | 0 | 34 | | await task; |
| | | 35 | | |
| | | 36 | | // Get result of task. |
| | 0 | 37 | | var taskWithReturnType = typeof(Task<>).MakeGenericType(responseType); |
| | 0 | 38 | | var resultProperty = taskWithReturnType.GetProperty(nameof(Task<object>.Result))!; |
| | 0 | 39 | | context.Response = resultProperty.GetValue(task)!; |
| | | 40 | | |
| | | 41 | | // Invoke next middleware. |
| | 0 | 42 | | await next(context); |
| | 0 | 43 | | } |
| | | 44 | | } |