private async Task InvokeQueryHandler(MessageInvocationContext context, Message message) { var resultType = GetQueryResultType(message.Body); var handlerType = typeof(IQueryHandler <,>).MakeGenericType(message.Body.GetType(), resultType); var handlers = _scope.Create(handlerType).ToList(); if (handlers.Count == 0) { throw new NoHandlerRegisteredException($"Missing handler for query '{message.Body}'."); } if (handlers.Count > 1) { throw new OnlyOneQueryHandlerAllowedException( $"Queries may only have one handler, '{message.Body}' got [{string.Join(", ", handlers.Select(x => x.GetType().FullName))}]."); } var handler = handlers[0]; Task task; Stopwatch sw = null; var args1 = new InvokingHandlerEventArgs(_scope, handler, message) { Principal = context.Principal }; try { if (HandlerInvoked != null) { sw = Stopwatch.StartNew(); } InvokingHandler?.Invoke(this, args1); task = (Task)handler .GetType() .GetMethod("HandleAsync") .Invoke(handler, new[] { context, message.Body }); await task; sw?.Stop(); var e = new HandlerInvokedEventArgs(_scope, handler, message, args1, sw?.Elapsed ?? TimeSpan.Zero) { Principal = context.Principal }; HandlerInvoked?.Invoke(this, e); } catch (Exception ex) { var e = new HandlerInvokedEventArgs(_scope, handler, message, args1.ApplicationState, sw?.Elapsed ?? TimeSpan.Zero) { Exception = ex }; HandlerInvoked?.Invoke(this, e); ExceptionDispatchInfo.Capture(ex).Throw(); return; } var resultProperty = typeof(Task <>).MakeGenericType(resultType).GetProperty("Result"); var result = resultProperty.GetValue(task); await context.ReplyAsync(result); }
private async Task InvokeMessageHandlers(IMessageContext context, Message message) { var messageType = message.Body.GetType(); var handleMethodParameterTypes = new Type[] { typeof(IMessageContext), messageType }; var type = typeof(IMessageHandler <>).MakeGenericType(messageType); var handlers = _scope.Create(type).ToList(); if (handlers.Count == 0) { Logger?.Invoke(LogLevel.Warning, message.MessageId.ToString("N"), "Missing handler for " + message.Body.GetType()); var e = new HandlerMissingEventArgs(context.Principal, message, _scope); HandlerMissing?.Invoke(this, e); if (e.Handler != null) { handlers.Add(e.Handler); } else if (e.ThrowException) { throw new NoHandlerRegisteredException("Failed to find handler for '" + message.Body + "'."); } else { return; } } if (InvokeHandlersInParallel) { var tasks = handlers.Select(async handler => { var mi = handler.GetType().GetMethod("HandleAsync", handleMethodParameterTypes); var task = (Task)mi.Invoke(handler, new[] { context, message.Body }); Stopwatch sw = null; var args1 = new InvokingHandlerEventArgs(_scope, handler, message) { Principal = context.Principal }; try { if (HandlerInvoked != null) { sw = Stopwatch.StartNew(); } Logger?.Invoke(LogLevel.Info, message.MessageId.ToString("N"), "Invoking " + handler.GetType()); InvokingHandler?.Invoke(this, args1); await task; sw?.Stop(); var e = new HandlerInvokedEventArgs(_scope, handler, message, args1, sw?.Elapsed ?? TimeSpan.Zero) { Principal = context.Principal }; HandlerInvoked?.Invoke(this, e); } catch (Exception ex) { Logger?.Invoke(LogLevel.Error, message.MessageId.ToString("N"), $"Handler failed: {handler.GetType()}, Exception: {ex}"); var e = new HandlerInvokedEventArgs(_scope, handler, message, args1.ApplicationState, sw?.Elapsed ?? TimeSpan.Zero) { Exception = ex, Principal = context.Principal }; HandlerInvoked?.Invoke(this, e); ExceptionDispatchInfo.Capture(ex).Throw(); } }).ToArray(); try { await Task.WhenAll(tasks); } catch (Exception) { var failedHandlers = new List <FailedHandler>(); for (var i = 0; i < handlers.Count; i++) { var task = tasks[i]; var handler = handlers[i]; if (task.IsFaulted) { failedHandlers.Add(new FailedHandler { Exception = task.Exception.InnerException, HandlerType = handler.GetType() }); } } throw new HandlersFailedException(message, failedHandlers); } } else { var failedHandlers = new List <FailedHandler>(); foreach (var handler in handlers) { var mi = handler.GetType().GetMethod("HandleAsync", handleMethodParameterTypes); var task = (Task)mi.Invoke(handler, new[] { context, message.Body }); Stopwatch sw = null; var args1 = new InvokingHandlerEventArgs(_scope, handler, message) { Principal = context.Principal }; try { if (HandlerInvoked != null) { sw = Stopwatch.StartNew(); } InvokingHandler?.Invoke(this, args1); await task; sw?.Stop(); var e = new HandlerInvokedEventArgs(_scope, handler, message, args1, sw?.Elapsed ?? TimeSpan.Zero) { Principal = context.Principal }; HandlerInvoked?.Invoke(this, e); } catch (Exception ex) { var e = new HandlerInvokedEventArgs(_scope, handler, message, args1.ApplicationState, sw?.Elapsed ?? TimeSpan.Zero) { Exception = ex, Principal = context.Principal }; HandlerInvoked?.Invoke(this, e); failedHandlers.Add(new FailedHandler() { Exception = ex, HandlerType = handlers.GetType() }); } } if (failedHandlers.Any()) { throw new HandlersFailedException(message, failedHandlers); } } }