public async Task ProcessAsync(IInvocationContext context, Message message) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } var messageContext = new MessageInvocationContext(context.Principal, message, this); // when messages arrive through the listener there is not difference between // messages and queries, since the result should be delivered over the queue. if (IsQuery(message.Body)) { await InvokeQueryHandler(messageContext, message); } else { await InvokeMessageHandlers(messageContext, message); } // someone else is taking care of the outbound messages if (_outboundMessageRouter != null) { Logger?.Invoke(LogLevel.Debug, "", "Invoking IOutboundMessageRouter."); await _outboundMessageRouter.SendAsync(messageContext); } foreach (var msg in messageContext.OutboundMessages) { Logger?.Invoke(LogLevel.Info, message.MessageId.ToString("N"), $"Sending {msg.Body.GetType()}"); await context.SendAsync(msg); } foreach (var msg in messageContext.Replies) { Logger?.Invoke(LogLevel.Info, message.MessageId.ToString("N"), $"Replying with {msg.Body.GetType()}"); await context.ReplyAsync(msg); } }
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); }