Exemple #1
0
            /// <summary>
            /// Provides the implementation for operations that invoke a member.
            /// Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can
            /// override this method to specify dynamic behavior for operations such as calling a method.
            /// This method should not be called directly, it is  called through dynamic method calls.
            /// </summary>
            /// <param name="binder">
            /// Provides information about the dynamic operation.
            /// The binder.Name property provides the name of the member on which the dynamic operation is performed.
            /// For example, for the statement sampleObject.SampleMethod(100), where sampleObject is an instance of the
            /// class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Name returns "SampleMethod".
            /// The binder.IgnoreCase property specifies whether the member name is case-sensitive.
            /// </param>
            /// <param name="args">
            /// The arguments that are passed to the object member during the invoke operation. For example,
            /// for the statement sampleObject.SampleMethod(100), where sampleObject is derived from the
            /// <see cref="T:System.Dynamic.DynamicObject"/> class, the first argument to <paramref name="args"/> is equal to 100.
            /// </param>
            /// <param name="result">The result of the member invocation.</param>
            /// <returns>
            /// true if the operation is successful; otherwise, false. If this method returns false, the run-time
            /// binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.)
            /// </returns>
            /// <exception cref="InvalidOperationException">
            /// Dynamic method is called with non-named argument.
            /// All parameters must be passed as name arguments to API calls.
            /// - or -
            /// The dynamic method name was not in the correct format.
            /// All API function calls must be in the format 'FunctionName###' where the optional ###'s represent a version number.
            /// </exception>
            /// <exception cref="ArgumentException">
            /// The reserved named parameter 'secure' was not a boolean value.
            /// This parameter is used when requests must go through the secure API.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            /// The function version number specified was out of range.
            /// </exception>
            public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
            {
                bool success = asyncInterface.TryInvokeMember(binder, args, out result);

                // the async interface's return of TryInvokeMember will be a Task<KeyValue>, but users of this interface class
                // expect a non-future KeyValue, so we need to duplicate the timeout handling logic here
                // to return a KeyValue, or throw an exception

                Task <KeyValue> resultTask = result as Task <KeyValue>;

                try
                {
                    bool completed = resultTask.Wait(Timeout);

                    if (!completed)
                    {
                        throw new TimeoutException("The WebAPI call timed out");
                    }
                }
                catch (AggregateException ex) when(ex.InnerException != null)
                {
                    // because we're internally using the async interface, any WebExceptions thrown will
                    // be wrapped inside an AggregateException.
                    // since callers don't expect this, we need to unwrap and rethrow the inner exception
                    ExceptionDispatchInfo.Capture(ex.InnerException).Throw();
                }

                result = resultTask.Result;

                return(success);
            }
Exemple #2
0
            /// <summary>
            /// Provides the implementation for operations that invoke a member.
            /// Classes derived from the <see cref="T:System.Dynamic.DynamicObject"/> class can
            /// override this method to specify dynamic behavior for operations such as calling a method.
            /// This method should not be called directly, it is  called through dynamic method calls.
            /// </summary>
            /// <param name="binder">
            /// Provides information about the dynamic operation.
            /// The binder.Name property provides the name of the member on which the dynamic operation is performed.
            /// For example, for the statement sampleObject.SampleMethod(100), where sampleObject is an instance of the
            /// class derived from the <see cref="T:System.Dynamic.DynamicObject"/> class, binder.Name returns "SampleMethod".
            /// The binder.IgnoreCase property specifies whether the member name is case-sensitive.
            /// </param>
            /// <param name="args">
            /// The arguments that are passed to the object member during the invoke operation. For example,
            /// for the statement sampleObject.SampleMethod(100), where sampleObject is derived from the
            /// <see cref="T:System.Dynamic.DynamicObject"/> class, the first argument to <paramref name="args"/> is equal to 100.
            /// </param>
            /// <param name="result">The result of the member invocation.</param>
            /// <returns>
            /// true if the operation is successful; otherwise, false. If this method returns false, the run-time
            /// binder of the language determines the behavior. (In most cases, a language-specific run-time exception is thrown.)
            /// </returns>
            /// <exception cref="InvalidOperationException">
            /// Dynamic method is called with non-named argument.
            /// All parameters must be passed as name arguments to API calls.
            /// - or -
            /// The dynamic method name was not in the correct format.
            /// All API function calls must be in the format 'FunctionName###' where the optional ###'s represent a version number.
            /// </exception>
            /// <exception cref="ArgumentException">
            /// The reserved named parameter 'secure' was not a boolean value.
            /// This parameter is used when requests must go through the secure API.
            /// </exception>
            /// <exception cref="ArgumentOutOfRangeException">
            /// The function version number specified was out of range.
            /// </exception>
            public override bool TryInvokeMember(InvokeMemberBinder binder, object[] args, out object result)
            {
                bool success = asyncInterface.TryInvokeMember(binder, args, out result);

                // the async interface's return of TryInvokeMember will be a Task<KeyValue>, but users of this interface class
                // expect a non-future KeyValue, so we need to duplicate the timeout handling logic here
                // to return a KeyValue, or throw an exception

                Task <KeyValue> resultTask = result as Task <KeyValue>;

                try
                {
                    bool completed = resultTask.Wait(Timeout);

                    if (!completed)
                    {
                        throw new WebException("The WebAPI call timed out", WebExceptionStatus.Timeout);
                    }
                }
                catch (AggregateException ex)
                {
                    // because we're internally using the async interface, any WebExceptions thrown will
                    // be wrapped inside an AggregateException.
                    // since callers don't expect this, we need to unwrap and rethrow the inner exception

                    var innerEx = ex.InnerException;

                    // preserve stack trace when rethrowing inner exception
                    // see: http://stackoverflow.com/a/4557183/139147

                    var prepFunc = typeof(Exception).GetMethod("PrepForRemoting", BindingFlags.NonPublic | BindingFlags.Instance);
                    if (prepFunc != null)
                    {
                        // TODO: we can't use this on mono!
                        // .NET 4.5 comes with the machinery to preserve a stack trace: ExceptionDispatchInfo, but we target 4.0

                        prepFunc.Invoke(innerEx, new object[0]);
                    }

                    throw innerEx;
                }

                result = resultTask.Result;

                return(success);
            }