示例#1
0
        public async Task <IQueryable> ExecuteOperationAsync(
            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 = context.ImplementInstance.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.GetApiService <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 = await InvokeOperation(context.ImplementInstance, method, parameters, model);

            // Invoke preprocessing on the operation execution
            PerformPostEvent(context, cancellationToken);
            return(result);
        }
        /// <summary>
        /// Asynchronously executes an operation.
        /// </summary>
        /// <param name="context">
        /// The operation context.
        /// </param>
        /// <param name="cancellationToken">
        /// A cancellation token.
        /// </param>
        /// <returns>
        /// A task that represents the asynchronous
        /// operation whose result is a operation result.
        /// </returns>
        public async Task <IQueryable> ExecuteOperationAsync(OperationContext context, CancellationToken cancellationToken)
        {
            Ensure.NotNull(context, nameof(context));

            // Authorization check
#pragma warning disable CA1062 // Validate arguments of public methods. JWS: Ensure.NotNull is there. Spurious warning.
            await InvokeAuthorizers(context, cancellationToken).ConfigureAwait(false);

#pragma warning restore CA1062 // Validate arguments of public methods.

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

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

            var parameterArray = method.GetParameters();

            var model = await context.Api.GetModelAsync(cancellationToken).ConfigureAwait(false);

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

            var 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.Request.GetRequestContainer()); // JWS: As long as OData requires the ServiceProvder,
                                                                //      we have to provide it. DI abuse smell.
                }
                else
                {
                    convertedValue = DeserializationHelpers.ConvertCollectionType(
                        currentParameterValue, parameter.ParameterType);
                }

                parameters[paraIndex] = convertedValue;
            }

            context.ParameterValues = parameters;

            // Invoke preprocessing on the operation execution
            await PerformPreEvent(context, cancellationToken).ConfigureAwait(false);

            var result = await InvokeOperation(context.Api, method, parameters, model).ConfigureAwait(false);

            // Invoke preprocessing on the operation execution
            await PerformPostEvent(context, cancellationToken).ConfigureAwait(false);

            return(result);
        }