/// <inheritdoc/>
 public Task OnOperationExecutedAsync(
     OperationContext context,
     CancellationToken cancellationToken)
 {
     return this.InvokeProcessorMethodAsync(
         context, ConventionBasedChangeSetConstants.FilterMethodNamePostFilterSuffix);
 }
        /// <inheritdoc/>
        public Task<bool> AuthorizeAsync(
            OperationContext context,
            CancellationToken cancellationToken)
        {
            Ensure.NotNull(context, "context");
            bool result = true;

            Type returnType = typeof(bool);
            var methodName = ConventionBasedChangeSetConstants.AuthorizeMethodActionInvocationExecute +
                        context.OperationName;
            MethodInfo method = this.targetType.GetQualifiedMethod(methodName);

            if (method != null && method.IsFamily &&
                method.ReturnType == returnType)
            {
                object target = null;
                if (!method.IsStatic)
                {
                    target = context.ImplementInstance;
                    if (target == null ||
                        !this.targetType.IsInstanceOfType(target))
                    {
                        return Task.FromResult(result);
                    }
                }

                var parameters = method.GetParameters();
                if (parameters.Length == 0)
                {
                    result = (bool)method.Invoke(target, null);
                }
            }

            return Task.FromResult(result);
        }
        private Task InvokeProcessorMethodAsync(
            OperationContext context,
            string methodNameSuffix)
        {
            string methodName = ConventionBasedChangeSetConstants.FilterMethodActionInvocationExecute +
                    methodNameSuffix + context.OperationName;
            object[] parameters = null;
            if (context.ParameterValues != null)
            {
                context.ParameterValues.ToArray();
            }

            MethodInfo method = this.targetType.GetQualifiedMethod(methodName);

            if (method != null &&
                (method.ReturnType == typeof(void) ||
                typeof(Task).IsAssignableFrom(method.ReturnType)))
            {
                object target = null;
                if (!method.IsStatic)
                {
                    target = context.ImplementInstance;
                    if (target == null ||
                        !this.targetType.IsInstanceOfType(target))
                    {
                        return Task.WhenAll();
                    }
                }

                ParameterInfo[] methodParameters = method.GetParameters();
                if (ParametersMatch(methodParameters, parameters))
                {
                    object result = method.Invoke(target, parameters);
                    Task resultTask = result as Task;
                    if (resultTask != null)
                    {
                        return resultTask;
                    }
                }
            }

            return Task.WhenAll();
        }
        public async Task<IQueryable> ExecuteOperationAsync(
            object instanceImplementMethod, OperationContext context, CancellationToken cancellationToken)
        {
            // Authorization check
            await InvokeAuthorizers(context, cancellationToken);

            // model build does not support operation with same name
            // So method with same name but different signature is not considered.
            MethodInfo method = instanceImplementMethod.GetType().GetMethod(
                context.OperationName, BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy);

            if (method == null)
            {
                throw new NotImplementedException(Resources.OperationNotImplemented);
            }

            var parameterArray = method.GetParameters();

            var model = context.ServiceProvider.GetService<IEdmModel>();

            // Parameters of method and model is exactly mapped or there is parsing error
            var parameters = new object[parameterArray.Length];

            int paraIndex = 0;
            if (context.BindingParameterValue != null)
            {
                // Add binding parameter which is first parameter of method
                parameters[0] = PrepareBindingParameter(parameterArray[0].ParameterType, context.BindingParameterValue);
                paraIndex = 1;
            }

            for (; paraIndex < parameterArray.Length; paraIndex++)
            {
                var parameter = parameterArray[paraIndex];
                var currentParameterValue = context.GetParameterValueFunc(parameter.Name);

                object convertedValue = null;
                if (context.IsFunction)
                {
                    var parameterTypeRef = parameter.ParameterType.GetTypeReference(model);

                    // Change to right CLR class for collection/Enum/Complex/Entity
                    convertedValue = DeserializationHelpers.ConvertValue(
                        currentParameterValue,
                        parameter.Name,
                        parameter.ParameterType,
                        parameterTypeRef,
                        model,
                        context.Request,
                        context.ServiceProvider);
                }
                else
                {
                    convertedValue = DeserializationHelpers.ConvertCollectionType(
                        currentParameterValue, parameter.ParameterType);
                }

                parameters[paraIndex] = convertedValue;
            }

            context.ParameterValues = parameters;

            // Invoke preprocessing on the operation execution
            PerformPreEvent(context, cancellationToken);

            var result = InvokeOperation(instanceImplementMethod, method, parameters, model);

            // Invoke preprocessing on the operation execution
            PerformPostEvent(context, cancellationToken);
            return result;
        }
 private static void PerformPostEvent(OperationContext context, CancellationToken cancellationToken)
 {
     var processor = context.ServiceProvider.GetService<IOperationFilter>();
     if (processor != null)
     {
         processor.OnOperationExecutedAsync(context, cancellationToken);
     }
 }
        private static async Task InvokeAuthorizers(
            OperationContext context,
            CancellationToken cancellationToken)
        {
            var authorizor = context.GetApiService<IOperationAuthorizer>();
            if (authorizor == null)
            {
                return;
            }

            if (!await authorizor.AuthorizeAsync(context, cancellationToken))
            {
                throw new SecurityException(string.Format(
                    CultureInfo.InvariantCulture, Resources.OperationUnAuthorizationExecution, context.OperationName));
            }
        }
 private Task<IQueryable> ExecuteOperationAsync(
     Func<string, object> getParaValueFunc,
     string operationName,
     bool isFunction,
     IQueryable bindingParameterValue,
     CancellationToken cancellationToken)
 {
     var executor = Api.Context.GetApiService<IOperationExecutor>();
     var context = new OperationContext(
         getParaValueFunc, operationName, Api, isFunction, bindingParameterValue);
     context.ServiceProvider = Request.GetRequestContainer();
     context.Request = Request;
     var result = executor.ExecuteOperationAsync(Api, context, cancellationToken);
     return result;
 }