예제 #1
0
        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));
        }
예제 #2
0
        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));
        }
예제 #3
0
        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);
        }
예제 #4
0
        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
            }));
        }
예제 #5
0
 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));
     }
 }
예제 #6
0
        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));
        }
예제 #7
0
        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;
            }
        }
예제 #8
0
        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));
            }
        }
예제 #9
0
        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
        }