예제 #1
0
        public QueryInfo(Type queryType, ICqrsOptions options)
        {
            QueryType   = queryType;
            IsAsync     = queryType.IsAssignableToGenericType(typeof(IAsyncQuery <>));
            ResultType  = DetermineResultTypes(queryType, IsAsync).Single();
            HttpMethods = queryType
                          .GetCustomAttributes(true)
                          .OfType <HttpMethodAttribute>()
                          .SelectMany(x => x.HttpMethods)
                          .Distinct()
                          .ToArray();

            if (!HttpMethods.Any())
            {
                HttpMethods = options.DefaultQueryHttpMethods;
            }

            if (IsAsync)
            {
                QueryHandlerType = typeof(IAsyncQueryHandler <,>).MakeGenericType(QueryType, ResultType);
            }
            else
            {
                QueryHandlerType = typeof(IQueryHandler <,>).MakeGenericType(QueryType, ResultType);
            }
        }
예제 #2
0
        private async Task HandleCommand(HttpContext context, ICqrsOptions options)
        {
            var path = options.GetCommandPath(context.Request.Path.Value);

            if (!_commandTypes.Value.ContainsKey(path))
            {
                throw new CommandNotFoundException($"Command '{path}' not found");
            }

            dynamic result = null;

            var info            = _commandTypes.Value[path];
            var exposeAttribute = info.CommandType.GetCustomAttribute <ExposeAttribute>();
            var formatter       = _registry.GetFormatter(exposeAttribute.Formatter);

            var deserializeMethod = _deserializeMethods.GetOrAdd(info.CommandType, (t) =>
            {
                var mi = CreateDeserializeLambdaMethodInfo.MakeGenericMethod(t);
                return(mi.Invoke(null, null));
            });

            dynamic command = await deserializeMethod(formatter, context.Request);

            dynamic handler = _container.GetInstance(info.CommandHandlerType);

            context.Items[ContextKey] = new CqrsContext(context.Request.Path.Value, path, CqrsType.Command, info.CommandHandlerType);

            if (info.IsGeneric)
            {
                if (info.IsAsync)
                {
                    result = await handler.HandleAsync(command, context.RequestAborted);
                }
                else
                {
                    result = handler.Handle(command);
                }
            }
            else
            {
                if (info.IsAsync)
                {
                    await handler.HandleAsync(command, context.RequestAborted);
                }
                else
                {
                    handler.Handle(command);
                }
            }

            CloseSession();

            var json = result is string?result : await formatter.SerializeAsync(result, context.Request);

            context.Response.ContentType = formatter.ContentType;
            context.Response.StatusCode  = (int)HttpStatusCode.OK;

            await HttpResponseWritingExtensions.WriteAsync(context.Response, json, context.RequestAborted);
        }
예제 #3
0
        private async Task HandleQuery(HttpContext context, ICqrsOptions options)
        {
            var path   = context.Request.Path.Value;
            var method = context.Request.Method;

            if (!_queryTypes.Value.ContainsKey($"{method} {path}"))
            {
                throw new QueryNotFoundException($"Query '{method} {path}' not found");
            }

            var info            = _queryTypes.Value[$"{method} {path}"];
            var exposeAttribute = info.QueryType.GetCustomAttribute <ExposeAttribute>();
            var formatter       = _registry.GetFormatter(exposeAttribute.Formatter);

            var deserializeMethod = _deserializeMethods.GetOrAdd(info.QueryType, (t) =>
            {
                var mi = CreateDeserializeLambdaMethodInfo.MakeGenericMethod(t);
                return(mi.Invoke(null, null));
            });

            var query = await deserializeMethod(formatter, context.Request);

            dynamic handler = options.GetInstance(info.QueryHandlerType);

            context.Items[IOwinContextExtensions.ContextKey] = new CqrsContext(context.Request.Path.Value, path, CqrsType.Command, info.QueryHandlerType);

            dynamic result;

            if (info.IsAsync)
            {
                result = await handler.HandleAsync(query, context.RequestAborted);
            }
            else
            {
                result = handler.Handle(query);
            }

            string json = null;

            if (result != null)
            {
                json = result is string?result : await formatter.SerializeAsync(result, context.Request);
            }

            context.Response.ContentType = formatter.ContentType;

            if (json != null)
            {
                context.Response.StatusCode = (int)HttpStatusCode.OK;
                await context.Response.WriteAsync(json, context.RequestAborted);
            }
            else
            {
                context.Response.StatusCode = (int)HttpStatusCode.NoContent;
            }
        }
예제 #4
0
        public QueryHandlerMiddleware(CqrsFormatterRegistry registry, ICqrsOptions options)
        {
            _registry = registry;
            _options  = options;

            _queryTypes = new Lazy <Dictionary <string, QueryInfo> >(() => options.GetQueryTypes()
                                                                     .SelectMany(x => x.HttpMethods, (ci, method) => new { QueryInfo = ci, HttpMethod = method })
                                                                     .ToDictionary(
                                                                         keySelector: (x) => $"{x.HttpMethod} {options.GetQueryPath(x.QueryInfo)}",
                                                                         elementSelector: x => x.QueryInfo,
                                                                         comparer: StringComparer.OrdinalIgnoreCase));
        }
예제 #5
0
        private async Task HandleCommand(HttpContext context, ICqrsOptions options)
        {
            var path = options.GetCommandPath(context.Request.Path.Value);

            if (!_commandTypes.ContainsKey(path))
            {
                throw new CommandNotFoundException($"Command '{path}' not found");
            }

            dynamic result = null;

            var info = _commandTypes[path];

            var     commandData = await new StreamReader(context.Request.Body).ReadToEndAsync();
            dynamic command     = DeserializeCommand(commandData, info.CommandType);

            dynamic handler = _container.GetInstance(info.CommandHandlerType);

            context.Items[ContextKey] = new CqrsContext(context.Request.Path.Value, path, CqrsType.Command, info.CommandHandlerType);

            if (info.IsGeneric)
            {
                if (info.IsAsync)
                {
                    result = await handler.HandleAsync(command, context.RequestAborted);
                }
                else
                {
                    result = handler.Handle(command);
                }
            }
            else
            {
                if (info.IsAsync)
                {
                    await handler.HandleAsync(command, context.RequestAborted);
                }
                else
                {
                    handler.Handle(command);
                }
            }

            CloseSession();

            var json = result is string?result : JsonConvert.SerializeObject(result, _jsonSerializerSettings);

            context.Response.ContentType = ContentType;
            context.Response.StatusCode  = (int)HttpStatusCode.OK;

            await HttpResponseWritingExtensions.WriteAsync(context.Response, json, context.RequestAborted);
        }
예제 #6
0
        public CommandInfo(Type commandType, ICqrsOptions options)
        {
            CommandType = commandType;
            IsAsync     = typeof(IAsyncCommand).IsAssignableFrom(commandType) ||
                          commandType.GetTypeInfo().IsAssignableToGenericType(typeof(IAsyncCommand <>));
            IsGeneric = commandType.GetTypeInfo().IsAssignableToGenericType(typeof(ICommand <>)) ||
                        commandType.GetTypeInfo().IsAssignableToGenericType(typeof(IAsyncCommand <>));
            GenericTypes = new[] { CommandType };
            HttpMethods  = commandType
                           .GetCustomAttributes(true)
                           .OfType <HttpMethodAttribute>()
                           .SelectMany(x => x.HttpMethods)
                           .Distinct()
                           .ToArray();

            if (!HttpMethods.Any())
            {
                HttpMethods = options.DefaultCommandHttpMethods;
            }

            if (IsGeneric)
            {
                ResultType   = DetermineResultTypes(commandType, IsAsync).Single();
                GenericTypes = GenericTypes.Union(new[] { ResultType }).ToArray();
            }

            if (IsAsync)
            {
                if (IsGeneric)
                {
                    CommandHandlerType = typeof(IAsyncCommandHandler <,>).MakeGenericType(GenericTypes);
                }
                else
                {
                    CommandHandlerType = typeof(IAsyncCommandHandler <>).MakeGenericType(GenericTypes);
                }
            }
            else
            {
                if (IsGeneric)
                {
                    CommandHandlerType = typeof(ICommandHandler <,>).MakeGenericType(GenericTypes);
                }
                else
                {
                    CommandHandlerType = typeof(ICommandHandler <>).MakeGenericType(GenericTypes);
                }
            }
        }
예제 #7
0
        public CqrsMiddleware(Container container, ICqrsOptions options)
        {
            _container = container;
            _options   = options;
            _jsonSerializerSettings = options.GetJsonSerializerSettings();

            _commandTypes = options.GetCommandTypes().ToDictionary(
                keySelector: options.GetCommandKey,
                elementSelector: type => type,
                comparer: StringComparer.OrdinalIgnoreCase);

            _queryTypes = options.GetQueryTypes().ToDictionary(
                keySelector: options.GetQueryKey,
                elementSelector: info => info,
                comparer: StringComparer.OrdinalIgnoreCase);
        }
예제 #8
0
        public CqrsMiddleware(Container container, CqrsFormatterRegistry registry, ICqrsOptions options)
        {
            _container = container;
            _registry  = registry;
            _options   = options;

            _commandTypes = new Lazy <Dictionary <string, CommandInfo> >(() => options.GetCommandTypes().ToDictionary(
                                                                             keySelector: options.GetCommandKey,
                                                                             elementSelector: type => type,
                                                                             comparer: StringComparer.OrdinalIgnoreCase));

            _queryTypes = new Lazy <Dictionary <string, QueryInfo> >(() => options.GetQueryTypes().ToDictionary(
                                                                         keySelector: options.GetQueryKey,
                                                                         elementSelector: info => info,
                                                                         comparer: StringComparer.OrdinalIgnoreCase));
        }
예제 #9
0
        private async Task HandleQuery(HttpContext context, ICqrsOptions options)
        {
            var path = options.GetQueryPath(context.Request.Path.Value);

            if (!_queryTypes.ContainsKey(path))
            {
                throw new QueryNotFoundException($"Query '{path}' not found");
            }

            // GET operations get their data through the query string, while POST operations expect a JSON
            // object being put in the body.
            var queryData = context.Request.Method == HttpMethod.Get.Method
                ? SerializationHelpers.ConvertQueryStringToJson(context.Request.QueryString.Value)
                : await new StreamReader(context.Request.Body).ReadToEndAsync();

            var info  = _queryTypes[path];
            var query = DeserializeQuery(queryData, info.QueryType);

            dynamic handler = _container.GetInstance(info.QueryHandlerType);

            context.Items[ContextKey] = new CqrsContext(context.Request.Path.Value, path, CqrsType.Command, info.QueryHandlerType);

            dynamic result;

            if (info.IsAsync)
            {
                result = await handler.HandleAsync(query, context.RequestAborted);
            }
            else
            {
                result = handler.Handle(query);
            }

            var json = result is string?result : JsonConvert.SerializeObject(result, _jsonSerializerSettings);

            context.Response.ContentType = ContentType;
            context.Response.StatusCode  = (int)HttpStatusCode.OK;

            await HttpResponseWritingExtensions.WriteAsync(context.Response, json, context.RequestAborted);
        }