private QueryHandlerWrapper <TResponse> GetWrappedHandlers <TResponse>(IQueryRequest <TResponse> query) { Type[] typeArgs = { query.GetType(), typeof(TResponse) }; var handlerType = typeof(IQueryRequestHandler <,>).MakeGenericType(typeArgs); var wrapperType = typeof(QueryHandlerWrapper <,>).MakeGenericType(typeArgs); var handlers = (IEnumerable)_serviceProvider.GetRequiredService(typeof(IEnumerable <>).MakeGenericType(handlerType)); var wrappedHandlers = (QueryHandlerWrapper <TResponse>)QueryHandlers.GetOrAdd(query.GetType(), handlers.Cast <object>() .Select(_ => (QueryHandlerWrapper <TResponse>)Activator.CreateInstance(wrapperType)).FirstOrDefault()); return(wrappedHandlers); }
public TResponse Execute <TResponse>(IQueryRequest <TResponse> request) where TResponse : IQueryResponse { var requestType = request.GetType(); _logger.InfoFormat("Building and executing pipeline for {RequestType}", requestType.Name); // todo: c# 7 tuples to the rescue pls! var deconstructMe = ResolveHandler(requestType); var handlerType = deconstructMe.Item1; var handler = deconstructMe.Item2; var requestContext = CreateRequestContext(); handler.Context = requestContext; var decorators = GetDecorators <TResponse>(handlerType.GetMethod(nameof(IQueryHandler <IQueryRequest <TResponse>, TResponse> .Execute)), requestContext); _logger.Debug("Begin building pipeline..."); var pipeline = new List <Func <IQueryRequest <TResponse>, TResponse> > { r => handler.Execute((dynamic)r) }; // fallback is doesn't have an incoming pipeline Func <IQueryRequest <TResponse>, TResponse> fallback = r => handler.Fallback((dynamic)r); foreach (var decorator in decorators) { _logger.DebugFormat("Adding decorator to pipeline: {Decorator}", decorator.GetType().Name); var next = pipeline.Last(); pipeline.Add(r => decorator.Execute(r, next, fallback)); } try { _logger.DebugFormat("Invoking pipeline..."); return(pipeline.Last().Invoke(request)); } catch (Exception ex) { _logger.InfoException("An exception was thrown during pipeline execution", ex); throw; } }
public async Task <TResponse> ExecuteAsync <TResponse>(IQueryRequest <TResponse> request, CancellationToken cancellationToken = default(CancellationToken)) where TResponse : IQueryResponse { var requestType = request.GetType(); _logger.InfoFormat("Building and executing async pipeline for {RequestType}", requestType.Name); // todo: c# 7 tuples to the rescue pls! var deconstructMe = ResolveHandler(requestType); var handlerType = deconstructMe.Item1; var handler = deconstructMe.Item2; var requestContext = CreateRequestContext(); handler.Context = requestContext; var decorators = GetDecorators <TResponse>(handlerType.GetMethod(nameof(IQueryHandler <IQueryRequest <TResponse>, TResponse> .ExecuteAsync)), requestContext); _logger.Debug("Begin building async pipeline..."); var pipeline = new List <Func <IQueryRequest <TResponse>, CancellationToken, Task <TResponse> > > { (r, ct) => handler.ExecuteAsync((dynamic)r, ct) }; // fallback is doesn't have an incoming pipeline Func <IQueryRequest <TResponse>, CancellationToken, Task <TResponse> > fallback = (r, ct) => handler.FallbackAsync((dynamic)r, ct); foreach (var decorator in decorators) { _logger.DebugFormat("Adding decorator to async pipeline: {Decorator}", decorator.GetType().Name); var next = pipeline.Last(); pipeline.Add((r, ct) => decorator.ExecuteAsync(r, next, fallback, ct)); } try { _logger.DebugFormat("Invoking async pipeline..."); return(await pipeline.Last().Invoke(request, cancellationToken).ConfigureAwait(false)); } catch (Exception ex) { _logger.InfoException("An exception was thrown during async pipeline execution", ex); throw; } }