private Type GetControllerTypeForCommand(CqrsInfo info) { if (info.IsAsync) { if (info.RspType == null) { return(typeof(CommandControllerAsyncBase <,>).MakeGenericType(info.ReqType, info.GetHandlerType())); } else { return(typeof(CommandControllerAsyncReturnBase <, ,>).MakeGenericType(info.ReqType, info.GetHandlerType(), info.RspType)); } } else { if (info.RspType == null) { return(typeof(CommandControllerBase <,>).MakeGenericType(info.ReqType, info.GetHandlerType())); } else { return(typeof(CommandControllerReturnBase <, ,>).MakeGenericType(info.ReqType, info.GetHandlerType(), info.RspType)); } } }
private Type GetControllerTypeForQuery(CqrsInfo info) { bool inputParams = info.ReqType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty).Any(); if (info.IsAsync) { if (inputParams) { return(typeof(QueryControllerAsyncBase <, ,>).MakeGenericType(info.ReqType, info.GetHandlerType(), info.RspType)); } else { return(typeof(QueryControllerVoidAsyncBase <, ,>).MakeGenericType(info.ReqType, info.GetHandlerType(), info.RspType)); } } else { if (inputParams) { return(typeof(QueryControllerBase <, ,>).MakeGenericType(info.ReqType, info.GetHandlerType(), info.RspType)); } else { return(typeof(QueryControllerVoidBase <, ,>).MakeGenericType(info.ReqType, info.GetHandlerType(), info.RspType)); } } }
public static string GetUrlPath(this CqrsControllerConfiguration options, CqrsInfo info) { var root = (info.IsQuery ? options.QueriesPath : options.CommandsPath).Replace("//", "/").TrimEnd('/').TrimStart('/'); var uri = $"/{root}/{info.MethodName}"; return(uri); }
private void MapExpose(TypeBuilder builder, CqrsInfo info) { MapAttribute <ExposeAttribute>(info.ReqType, (attr) => { var uri = _options.GetUrlPath(info); builder.AddAttribute(typeof(Microsoft.AspNetCore.Mvc.RouteAttribute), new object[] { uri }); builder.AddAttribute(typeof(OutputFormatterAttribute), new object[1] { attr.Formatter ?? "" }); }); }
private void CreateController(CqrsInfo info) { var controllerBaseType = info.IsQuery ? GetControllerTypeForQuery(info) : GetControllerTypeForCommand(info); var typeBuilder = _moduleBuilder.CreateNewTypeFromExistingType(controllerBaseType, info.MethodName); MapExpose(typeBuilder, info); MapResponseType(typeBuilder, info.RspType); MapAuthorize(typeBuilder, info.ReqType); if (_options.CopyAttributes) { CopyAttributes(typeBuilder, info.ReqType); } typeBuilder.CreateTypeInfo(); }
public static async Task <TChRspEnvelope> HandleChannelRequest <TReq, TRsp, TChReq, TChRsp, TChRspEnvelope>( Container container, IMapper mapper, ServerCallContext ctx, string serverId, CqrsInfo info, TChReq chReq, CancellationToken cancellationToken = default) { GrpcResponseEnvelope <TRsp> rsp = null; Exception exception = null; // get logger var logger = (container.TryGetInstance(typeof(ILoggerFactory)) as ILoggerFactory)?.CreateLogger("CqrsGrpcServer"); // get aspect var aspect = container.TryGetInstance(typeof(IGrpcServerAspect)) as IGrpcServerAspect; // call recieved aspect?.OnCallRecieved(ctx); // name var name = chReq?.GetType()?.Name ?? "Unknown"; var watch = Stopwatch.StartNew(); try { // before execution logger?.LogDebug("Request {requestName} started on server {serverId}.", name, serverId); var req = mapper.Map <TReq>(chReq); aspect?.BeforeExecution(req); // execution function Func <Task <GrpcResponseEnvelope <TRsp> > > execFnc = () => { var processor = container.GetInstance <IGrpcCqrsServerProcessor>(); return(Task.Run(async() => await processor.ProcessRequestAsync <TReq, TRsp>(req, info, cancellationToken))); }; // execute rsp = await(aspect != null ? aspect.ExecuteAsync(container, execFnc) : execFnc.Invoke()); // execution completed var chRsp = mapper.Map <TChRspEnvelope>(rsp); watch.Stop(); logger?.LogInformation("Request {requestName} completed on server {serverId}. Call duration was {durationMs}ms.", name, serverId, watch.ElapsedMilliseconds); return(chRsp); } catch (ValidationErrorResponseException e) { exception = e; watch.Stop(); logger.LogInformation("Request {requestName} validation error on server {serverId}. Call duration was {durationMs}ms.", name, serverId, watch.ElapsedMilliseconds); rsp = new GrpcResponseEnvelope <TRsp> { IsValidationError = true, ValidationError = e.Response }; var chRsp = mapper.Map <TChRspEnvelope>(rsp); return(chRsp); } catch (Exception e) { exception = e; watch.Stop(); logger.LogError(e, "Request {requestName} failed on server {serverId}. Call duration was {durationMs}ms.", name, serverId, watch.ElapsedMilliseconds); rsp = new GrpcResponseEnvelope <TRsp> { IsExecutionError = true, ErrorMessage = e.Message }; var chRsp = mapper.Map <TChRspEnvelope>(rsp); return(chRsp); } finally { aspect?.AfterExecution(rsp, exception); } }
public async Task <GrpcResponseEnvelope <TResponse> > ProcessRequestAsync <TRequest, TResponse>(TRequest request, CqrsInfo info, CancellationToken cancellationToken) { if (info.IsCommand) { if (info.IsAsync) { if (info.RspType != null) { var cmd = request as IAsyncCommand <TResponse>; var rsp = await _commandDispatcher.DispatchAsync(cmd, cancellationToken); return(CreateResponseEnvelope(rsp)); } else { } } else { if (info.RspType != null) { var cmd = request as ICommand <TResponse>; var rsp = await Task.Run(() => { return(_commandDispatcher.Dispatch(cmd)); }, cancellationToken); return(CreateResponseEnvelope(rsp)); } } } if (info.IsQuery) { if (info.IsAsync) { var query = request as IAsyncQuery <TResponse>; var rsp = await _queryProcessor.HandleAsync(query, cancellationToken); return(CreateResponseEnvelope(rsp)); } else { var query = request as IQuery <TResponse>; var rsp = await Task.Run(() => { return(_queryProcessor.Handle(query)); }, cancellationToken); return(CreateResponseEnvelope(rsp)); } } // not supported return(CreateResponseEnvelopeError <TResponse>("Not supported request.")); }