예제 #1
0
        private ControllerFunction CreateControllerFunction(ControllerMethod controllerMethod)
        {
            var httpContextArgument = Expression.Parameter(typeof(IHttpContext), "httpContext");
            var modelBinderArgument = Expression.Parameter(typeof(IModelBinder), "modelBinder");
            var controllerArgument = Expression.Parameter(typeof(object), "controller");

            var errorContainerVariable = Expression.Variable(typeof(IErrorContainer));

            var foundMethod =
                (from method in controllerMethod.ControllerType.GetMethods(BindingFlags.Instance | BindingFlags.Public)
                 let attribute = method.GetCustomAttribute<HttpMethodAttribute>()
                 where attribute != null && attribute.HttpMethod == controllerMethod.Method
                 select method).FirstOrDefault();

            if (foundMethod == null)
            {
                return MethodNotFoundControllerFunction;
            }

            var parameters = foundMethod.GetParameters();

            IList<ParameterExpression> variables = new List<ParameterExpression>(parameters.Length);

            IList<Expression> body = new List<Expression>(parameters.Length);

            var modelBindingGetMethod = typeof(IModelBinding).GetMethods()[0];

            foreach (var parameter in parameters)
            {
                var variable = Expression.Variable(parameter.ParameterType, parameter.Name);
                variables.Add(variable);

                var attributes = parameter.GetCustomAttributes().ToList();

                var modelBindingAttribute = attributes.OfType<IModelBinding>().Single();

                body.Add(
                    Expression.Assign(variable,
                        Expression.Call(Expression.Constant(modelBindingAttribute),
                            modelBindingGetMethod.MakeGenericMethod(parameter.ParameterType),
                            httpContextArgument, modelBinderArgument
                            )));

                if (!attributes.OfType<NullableAttribute>().Any())
                {
                    body.Add(Expression.IfThen(Expression.Equal(variable, Expression.Constant(null)),
                        Expression.Call(errorContainerVariable, "Log", Type.EmptyTypes,
                            Expression.Constant(parameter.Name + " Is not found (null) and not marked as nullable."))));
                }

                if (parameter.ParameterType.GetInterfaces().Contains(typeof(IValidate)))
                {
                    body.Add(Expression.IfThen(Expression.NotEqual(variable, Expression.Constant(null)),
                        Expression.Call(variable, "Validate", Type.EmptyTypes, errorContainerVariable)));
                }

            }

            var methodCallExp = Expression.Call(Expression.Convert(controllerArgument, controllerMethod.ControllerType), foundMethod, variables);

            var labelTarget = Expression.Label(typeof(Task<IControllerResponse>));

            var parameterBindingExpression = body.Count > 0 ? (Expression)Expression.Block(body) : Expression.Empty();

            var methodBody = Expression.Block(
                variables.Concat(new[] { errorContainerVariable }),
                Expression.Assign(errorContainerVariable, Expression.New(typeof(ErrorContainer))),
                parameterBindingExpression,
                Expression.IfThen(Expression.Not(Expression.Property(errorContainerVariable, "Any")),
                        Expression.Return(labelTarget, methodCallExp)),

                Expression.Label(labelTarget, Expression.Call(errorContainerVariable, "GetResponse", Type.EmptyTypes))
                );

            var parameterExpressions = new[] { httpContextArgument, modelBinderArgument, controllerArgument };
            var lambda = Expression.Lambda<ControllerFunction>(methodBody, parameterExpressions);

            return lambda.Compile();
        }
예제 #2
0
 private bool Equals(ControllerMethod other)
 {
     return _controllerType == other._controllerType && _method == other._method;
 }
예제 #3
0
        private Task<IControllerResponse> CallMethod(IHttpContext context, IController controller)
        {
            var controllerMethod = new ControllerMethod(controller.GetType(), context.Request.Method);

            ControllerFunction controllerFunction;
            if (!ControllerFunctions.TryGetValue(controllerMethod, out controllerFunction))
            {
                lock (SyncRoot)
                {
                    if (!ControllerFunctions.TryGetValue(controllerMethod, out controllerFunction))
                    {
                        ControllerFunctions[controllerMethod] = controllerFunction = CreateControllerFunction(controllerMethod);
                    }
                }
            }

            return controllerFunction(context, this.ModelBinder, controller);
            //context.Response = await controllerResponse.Respond(context, _view).ConfigureAwait(false);
        }