public static FacetRequest CreateFrom(
            string facetName,
            string methodName,
            JsonArray jsonArguments,
            IEnumerable <Type> typesToSearch
            )
        {
            var request = new FacetRequest {
                FacetName     = facetName,
                MethodName    = methodName,
                JsonArguments = jsonArguments,
                FacetType     = Facet.FindFacetTypeByName(
                    facetName,
                    typesToSearch
                    )
            };

            request.Method = Facet.FindMethodByName(
                request.FacetType,
                methodName
                );

            request.Arguments = Facet.DeserializeArguments(
                request.Method,
                jsonArguments
                );

            request.Facet = Facet.CreateInstance(request.FacetType);

            return(request);
        }
        /// <summary>
        /// Extracts and sorts middleware layers from a facet request
        /// </summary>
        private static List <Layer> ObtainMiddlewareLayers(
            Application app,
            IEnumerable <MiddlewareAttribute> globalMiddleware,
            FacetRequest request
            )
        {
            var globalLayers = globalMiddleware
                               .Select(attr => new Layer(app, attr))
                               .OrderBy(l => l.order);

            var classLayers = request.FacetType
                              .GetCustomAttributes <MiddlewareAttribute>(inherit: true)
                              .Select(attr => new Layer(app, attr))
                              .OrderBy(l => l.order);

            var methodLayers = request.Method
                               .GetCustomAttributes <MiddlewareAttribute>(inherit: true)
                               .Select(attr => new Layer(app, attr))
                               .OrderBy(l => l.order);

            return(globalLayers
                   .Concat(classLayers)
                   .Concat(methodLayers)
                   .ToList());
        }
            private FacetResponse Next(FacetRequest request)
            {
                if (currentLayerIndex >= layers.Count)
                {
                    return(finalAction.Invoke(request));
                }

                var currentLayer = layers[currentLayerIndex];

                currentLayerIndex++;

                var response = currentLayer.middleware
                               .Handle(request, Next, currentLayer.parameters);

                // make sure null wasn't returned
                if (response == null)
                {
                    throw new NullReferenceException(
                              $"Middleware {currentLayer.middleware.GetType()} has "
                              + $"returned null when calling {request.FacetName}."
                              + $"{request.MethodName} Returning null from "
                              + "middleware is not allowed."
                              );
                }

                return(response);
            }
        /// <summary>
        /// Executes provided closure inside all middleware layers
        /// </summary>
        public static FacetResponse ExecuteMiddlewareStack(
            Application app,
            IEnumerable <MiddlewareAttribute> globalMiddleware,
            FacetRequest request,
            Func <FacetRequest, FacetResponse> action
            )
        {
            List <Layer> layers = ObtainMiddlewareLayers(
                app,
                globalMiddleware,
                request
                );

            LayerIterator iterator = new LayerIterator(
                layers,
                action
                );

            return(iterator.Iterate(request));
        }
 /// <summary>
 /// Handles a request, passes it to the next layer
 /// and returns the response
 /// </summary>
 public abstract FacetResponse Handle(
     FacetRequest request,
     Func <FacetRequest, FacetResponse> next,
     string[] parameters
     );
 public FacetResponse Iterate(FacetRequest request)
 {
     currentLayerIndex = 0;
     return(Next(request));
 }