/// <summary>
        /// Добавляет промежуточный класс обработки в конвейер обработки.
        /// </summary>
        /// <typeparam name="TMiddleware">Промежуточный класс обработки.</typeparam>
        /// <typeparam name="T">Тип обрабатываемого объекта.</typeparam>
        /// <param name="builder"><see cref="IMiddlewareBuilder{T}"/> объект.</param>
        /// <param name="args">Аргументы передаваемые в конструктор промежуточного класса обработки.</param>
        /// <returns><see cref="IMiddlewareBuilder{T}"/> объект.</returns>
        public static IMiddlewareBuilder <T> UseMiddleware <TMiddleware, T>(this IMiddlewareBuilder <T> builder, params object[] args) where TMiddleware : IMiddleware <T>
        {
            return(builder.Use(next =>
            {
                var middleware = typeof(TMiddleware);

                //Добавляется 1, так как конструктор типа наследуемого от IMiddleware<T>
                //первым аргументом должен принимать ссылку на следующий делегат
                var argsLength = args.Length + 1;

                if (!middleware
                    .GetConstructors()
                    .Any(c => c.GetParameters().Length != 0 &&
                         c.GetParameters()[0].ParameterType == typeof(Func <T, Task>) &&
                         c.GetParameters().Length.Equals(argsLength)))
                {
                    throw new InvalidOperationException($"The class [{middleware.Name}] does not have a suitable constructor");
                }

                var methodInfo = middleware.GetMethod(InvokeAsyncMethodName);

                var ctorArgs = new object[argsLength];
                ctorArgs[0] = next;
                Array.Copy(args, 0, ctorArgs, 1, args.Length);

                var instance = Activator.CreateInstance(middleware, ctorArgs);

                return (Func <T, Task>)methodInfo.CreateDelegate(typeof(Func <T, Task>), instance);
            }));
        }
        //private static bool IsSubclassOfRawGeneric(Type generic, Type toCheck)
        //{
        //    while (toCheck != null && toCheck != typeof(object))
        //    {
        //        var cur = toCheck.IsGenericType ? toCheck.GetGenericTypeDefinition() : toCheck;
        //        if (generic == cur)
        //        {
        //            return true;
        //        }
        //        toCheck = toCheck.BaseType;
        //    }
        //    return false;
        //}

        private static IMiddlewareBuilder <TContext> UseMiddlewareInterface <TContext>(IMiddlewareBuilder <TContext> app, Type middlewareType)
            where TContext : ContextBase
        {
            return(app.Use(next =>
            {
                return async context =>
                {
                    var middlewareFactory = (IMiddlewareFactory <TContext>)context.ContextServices.GetService(typeof(IMiddlewareFactory <TContext>));
                    if (middlewareFactory == null)
                    {
                        // No middleware factory
                        throw new InvalidOperationException("No middleware factory.");
                    }

                    var middleware = middlewareFactory.Create(middlewareType);
                    if (middleware == null)
                    {
                        throw new InvalidOperationException("The factory returned null, it's a broken implementation.");
                    }

                    try
                    {
                        await middleware.InvokeAsync(context, next);
                    }
                    finally
                    {
                        middlewareFactory.Release(middleware);
                    }
                };
            }));
        }
Beispiel #3
0
        /// <summary>
        /// Branches the request pipeline based on the result of the given predicate.
        /// </summary>
        /// <param name="app"></param>
        /// <param name="predicate">Invoked with the request environment to determine if the branch should be taken</param>
        /// <param name="configuration">Configures a branch to take</param>
        /// <returns></returns>
        public static IMiddlewareBuilder <TContext> MapWhen <TContext>(this IMiddlewareBuilder <TContext> app, Predicate <TContext> predicate, Action <IMiddlewareBuilder <TContext> > configuration)
            where TContext : ContextBase
        {
            if (app == null)
            {
                throw new ArgumentNullException(nameof(app));
            }

            if (predicate == null)
            {
                throw new ArgumentNullException(nameof(predicate));
            }

            if (configuration == null)
            {
                throw new ArgumentNullException(nameof(configuration));
            }

            // create branch
            var branchBuilder = app.New();

            configuration(branchBuilder);
            var branch = branchBuilder.Build();

            // put middleware in pipeline
            var options = new MapWhenOptions <TContext>
            {
                Predicate = predicate,
                Branch    = branch,
            };

            return(app.Use(next => new MapWhenMiddleware <TContext>(next, options).Invoke));
        }
        public static IMiddlewareBuilder <TContext> UseRoutes <TContext>(this IMiddlewareBuilder <TContext> self, params Route <TContext>[] routes) where TContext : Context
        {
            if (self == null)
            {
                throw new ArgumentNullException(nameof(self));
            }

            if (routes == null)
            {
                throw new ArgumentNullException(nameof(routes));
            }

            foreach (var route in routes)
            {
                if (route.IsApplicable == null)
                {
                    throw new ArgumentNullException(nameof(route.IsApplicable));
                }

                if (route.MiddlewareBuilderForRoute == null)
                {
                    throw new ArgumentNullException(nameof(route.MiddlewareBuilderForRoute));
                }
            }

            return(self.Use(InternalRouter.CreateMiddlewareFactory(self, routes)));
        }
Beispiel #5
0
 /// <summary>
 /// Упрощает добавление промежуточного делегата в конвейер обработки.
 /// </summary>
 /// <typeparam name="T">Обрабатываемый тип.</typeparam>
 /// <param name="builder"><see cref="IMiddlewareBuilder{T}"/> объект.</param>
 /// <param name="middleware">Функция обрабатывающая запрос или вызывает следующую в конвейере обработки.</param>
 /// <returns><see cref="IMiddlewareBuilder{T}"/> объект.</returns>
 public static IMiddlewareBuilder <T> Use <T>(this IMiddlewareBuilder <T> builder, Func <T, Func <Task>, Task> middleware)
 {
     return(builder.Use(next =>
     {
         return item => middleware(item, () => next(item));
     }));
 }
Beispiel #6
0
 public static IMiddlewareBuilder <TContext> Use <TContext>(this IMiddlewareBuilder <TContext> app, Func <TContext, Func <Task>, Task> middleware)
     where TContext : ContextBase
 {
     return(app.Use(next =>
     {
         return context =>
         {
             Func <Task> simpleNext = () => next(context);
             return middleware(context, simpleNext);
         };
     }));
 }
        public static IMiddlewareBuilder <TContext> UseMiddleware <TContext>(this IMiddlewareBuilder <TContext> builder, Type middleware, params object[] args)
            where TContext : ContextBase
        {
            if (typeof(IMiddleware <TContext>).GetTypeInfo().IsAssignableFrom(middleware.GetTypeInfo()))
            {
                if (args.Length > 0)
                {
                    throw new NotSupportedException("IMiddleware doesn't support passing args directly since it's");
                }

                return(UseMiddlewareInterface(builder, middleware));
            }

            var applicationServices = builder.ApplicationServices;

            return(builder.Use(next =>
            {
                var methods = middleware.GetMethods(BindingFlags.Instance | BindingFlags.Public);
                var invokeMethods = methods.Where(m =>
                                                  string.Equals(m.Name, InvokeMethodName, StringComparison.Ordinal) ||
                                                  string.Equals(m.Name, InvokeAsyncMethodName, StringComparison.Ordinal)
                                                  ).ToArray();

                if (invokeMethods.Length > 1)
                {
                    throw new InvalidOperationException($"Find over then one invoke methode.");
                }

                if (invokeMethods.Length == 0)
                {
                    throw new InvalidOperationException("Can't find invoke methode.");
                }

                var methodInfo = invokeMethods[0];
                if (!typeof(Task).IsAssignableFrom(methodInfo.ReturnType))
                {
                    throw new InvalidOperationException($"Invoke methode must return Task.");
                }

                var parameters = methodInfo.GetParameters();
                if (parameters.Length == 0 || parameters[0].ParameterType.BaseType != typeof(ContextBase))
                {
                    throw new InvalidOperationException($"Can't find methode {InvokeMethodName} or {InvokeAsyncMethodName} with parameters");
                }

                var ctorArgs = new object[args.Length + 1];
                ctorArgs[0] = next;
                Array.Copy(args, 0, ctorArgs, 1, args.Length);
                var instance = ActivatorUtilities.CreateInstance(builder.ApplicationServices, middleware, ctorArgs);
                if (parameters.Length == 1)
                {
                    return (MiddlewareDelegate <TContext>)methodInfo.CreateDelegate(typeof(MiddlewareDelegate <TContext>), instance);
                }

                var factory = Compile <object, TContext>(methodInfo, parameters);

                return context =>
                {
                    var serviceProvider = context.ContextServices ?? applicationServices;
                    if (serviceProvider == null)
                    {
                        throw new InvalidOperationException("ServiceProvider not available.");
                    }

                    return factory(instance, context, serviceProvider);
                };
            }));
        }
Beispiel #8
0
 public static IMiddlewareBuilder <TContext> Use <TContext>(this IMiddlewareBuilder <TContext> self, IMiddleware <TContext> middleware) where TContext : Context
 => self.Use(middleware.InvokeAsync);
Beispiel #9
0
 public static IMiddlewareBuilder <TContext> Run <TContext>(this IMiddlewareBuilder <TContext> self, MiddlewareDelegate <TContext> handler) where TContext : Context
 => self.Use(next => handler);
Beispiel #10
0
 public static IMiddlewareBuilder <TContext> Use <TContext>(this IMiddlewareBuilder <TContext> self, MiddlewareDelegate <TContext> middleware) where TContext : Context
 => self.Use(next => async context => { await middleware(context); await next(context); });
Beispiel #11
0
 public static IMiddlewareBuilder <TContext> Use <TContext>(this IMiddlewareBuilder <TContext> self, Func <TContext, MiddlewareDelegate <TContext>, Task> middleware) where TContext : Context
 => self.Use(factoryInputNext =>
 {
     return(context => middleware(context, factoryInputNext));
 });
Beispiel #12
0
 public static void Run <TContext>(this IMiddlewareBuilder <TContext> app, MiddlewareDelegate <TContext> handler)
     where TContext : ContextBase
 {
     app.Use(_ => handler);
 }
Beispiel #13
0
 public static IMiddlewareBuilder <TContext> UseJsonSerializer <T, TContext>(this IMiddlewareBuilder <TContext> self, Func <TContext, string> contentSelector, string argumentName) where TContext : Context
 {
     return(self.Use(JsonArgumentSerializer.CreateMiddlewareFactoryForJsonSerializer <T, TContext>(contentSelector, argumentName)));
 }
 public static IMiddlewareBuilder <TContext> UseRoutingKey <TContext>(this IMiddlewareBuilder <TContext> self, Func <TContext, string> routingKeySelector, params string[] routePatterns) where TContext : Context
 {
     return(self.Use(StringRouter.CreateRoutingKeyMiddlewareFactory <TContext>(routingKeySelector, routePatterns)));
 }
Beispiel #15
0
 public static IMiddlewareBuilder <TContext> UseRouting <TContext>(this IMiddlewareBuilder <TContext> self) where TContext : Context
 => self.Use(EndpointRouter.CreateRoutingSetupMiddlewareFactory(self));
Beispiel #16
0
 public static IMiddlewareBuilder <TContext> UseEndpoints <TContext>(this IMiddlewareBuilder <TContext> self, Action <IEndpointRouteBuilder <TContext> > endpoints) where TContext : Context
 => self.Use(EndpointRouter.CreateEndpointDispatcherMiddlewareFactory(self, endpoints));