private async Task <object> ProcessNextMiddleware <T>(T command, ICommandBusMiddleware <T>[] middlewares, int middlewareIndex, CommandBusMiddlewareDelegate executionHandler, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) where T : class, ICommandBase { CommandBusMiddlewareDelegate next; if (middlewareIndex == middlewares.Length - 1) { next = executionHandler; } else { next = async processedCommand => { var typedCommand = processedCommand as T ?? throw new ArgumentException( $"Command passed to command bus middleware ({processedCommand?.GetType()}) is not of original type {typeof(T)}"); return(await ProcessNextMiddleware <T>(typedCommand, middlewares, middlewareIndex + 1, executionHandler, executionOptions, cancellationToken)); }; } return(await middlewares[middlewareIndex].HandleAsync(command, executionOptions, next, cancellationToken)); }
public Task <TResult> SendAsync <TResult>(ICommand <TResult> command, CommandExecutionOptions executionOptions, CancellationToken cancellationToken = default(CancellationToken)) { var commandBus = commandRouter.FindRoute(command.GetType()) ?? throw new ArgumentException($"No route to a command bus found for command type {command.GetType()}"); return(commandBus.SendAsync(command, executionOptions, cancellationToken)); }
public async Task <TResult> SendAsync <TResult>(ICommand <TResult> command, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) { Type handlerType = typeof(ICommandHandler <,>).MakeGenericType(command.GetType(), typeof(TResult)); var result = await InvokeHandleAsync <TResult>(handlerType, command, executionOptions, cancellationToken); return(result); }
public Task <object> ProcessAsync(ICommandBase command, CommandBusMiddlewareDelegate executionHandler, ICommandBus commandBus, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) { var processMethod = GetType().GetRuntimeMethods().Single(x => x.Name == "ProcessInternalAsync"); var boundProcessMethod = processMethod.MakeGenericMethod(command.GetType()); return((Task <object>)boundProcessMethod.Invoke(this, new object[] { command, executionHandler, commandBus, executionOptions, cancellationToken })); }
public Task <object> HandleAsync(ICommandBase command, CommandExecutionOptions executionOptions, CommandBusMiddlewareDelegate next, CancellationToken cancellationToken) { if (executionOptions.AutoCommitUnitOfWork == true || (executionOptions.AutoCommitUnitOfWork == null && !IsQuery(command))) { using (var uow = unitOfWorkFactory.CreateUnitOfWork()) { return(HandleNext(command, next, uow)); } } else { return(HandleNext(command, next, null)); } }
public Task SendAsync(ICommandBase command, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) { Type genericCommandType = command.GetType().GetInterfaces().FirstOrDefault( x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(ICommand <>)); Type handlerType; if (genericCommandType != null) { handlerType = typeof(ICommandHandler <,>).MakeGenericType(command.GetType(), genericCommandType.GetGenericArguments()[0]); return(InvokeHandleAsync <object>(handlerType, command, executionOptions, cancellationToken)); } handlerType = typeof(ICommandHandler <>).MakeGenericType(command.GetType()); return(InvokeHandleAsync <object>(handlerType, command, executionOptions, cancellationToken)); }
public async Task <object> HandleAsync(T command, CommandExecutionOptions executionOptions, CommandBusMiddlewareDelegate next, CancellationToken cancellationToken) { await PreFilterAsync(command); try { var result = await next(command); await PostFilterAsync(command); return(result); } catch (Exception e) { await FilterExceptionAsync(command, e); throw; } }
private async Task <object> ProcessInternalAsync <T>(T command, CommandBusMiddlewareDelegate executionHandler, ICommandBus commandBus, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) where T : class, ICommandBase { using (TaskContext.Enter()) { var middlewares = middlewareFactory.CreateMiddlewares <T>(commandBus); if (middlewares.Length == 0) { return(executionHandler(command)); } middlewares = middlewares.OrderBy(x => x.Order).ToArray(); return(await ProcessNextMiddleware(command, middlewares, 0, executionHandler, executionOptions, cancellationToken)); } }
private async Task <TResult> InvokeHandleAsync <TResult>(Type handlerType, ICommandBase command, CommandExecutionOptions executionOptions, CancellationToken cancellationToken) { CommandBusMiddlewareDelegate executionHandler = async processedCommand => { if (processedCommand == null) { throw new ArgumentNullException(nameof(processedCommand)); } if (!command.GetType().IsInstanceOfType(processedCommand)) { throw new ArgumentException( $"Command passed back to command bus from a middleware is not of its original type {command.GetType()}"); } Type commandType = command.GetType(); object listener = serviceLocator.Get(handlerType); var handleMethod = listener.GetType() .GetRuntimeMethod(nameof(ICommandHandler <ICommand> .HandleAsync), new[] { commandType, typeof(CancellationToken) }); var resultTask = (Task)handleMethod.Invoke(listener, new object[] { command, cancellationToken }); if (resultTask is Task <TResult> resultObjectTask) { return(await resultObjectTask); } else { await resultTask; return(null); } }; object result = await pipeline.ProcessAsync(command, executionHandler, this, executionOptions, cancellationToken); return((TResult)result); // TODO test with contravariant handlers }