/// <summary>
        /// Invokes an operation asynchronously.
        /// </summary>
        /// <param name="invokeArgs">The arguments to the Invoke operation.</param>
        /// <param name="callback">The callback to invoke when the invocation has been completed.</param>
        /// <param name="userState">Optional user state that will be passed through on the <see cref="InvokeCompletedResult"/>.</param>
        /// <returns>An asynchronous result that identifies this invocation.</returns>
        /// <exception cref="InvalidOperationException">The specified query does not exist.</exception>
        protected sealed override IAsyncResult BeginInvokeCore(InvokeArgs invokeArgs, AsyncCallback callback, object userState)
        {
            MethodInfo beginInvokeMethod = WebDomainClient <TContract> .ResolveBeginMethod(invokeArgs.OperationName);

            MethodInfo endInvokeMethod = WebDomainClient <TContract> .ResolveEndMethod(invokeArgs.OperationName);

            // Pass operation parameters.
            ParameterInfo[] parameterInfos  = beginInvokeMethod.GetParameters();
            object[]        realParameters  = new object[parameterInfos.Length];
            int             parametersCount = (invokeArgs.Parameters == null) ? 0 : invokeArgs.Parameters.Count;

            for (int i = 0; i < parametersCount; i++)
            {
                realParameters[i] = invokeArgs.Parameters[parameterInfos[i].Name];
            }

            TContract channel = this.ChannelFactory.CreateChannel();
            WebDomainClientAsyncResult <TContract> wcfAsyncResult = WebDomainClientAsyncResult <TContract> .CreateInvokeResult(this, channel, endInvokeMethod, invokeArgs, callback, userState);

            // Pass async operation related parameters.
            realParameters[parameterInfos.Length - 2] = new AsyncCallback(delegate(IAsyncResult asyncResponseResult)
            {
                wcfAsyncResult.InnerAsyncResult = asyncResponseResult;
                wcfAsyncResult.Complete();
            });
            realParameters[parameterInfos.Length - 1] = userState;

            IAsyncResult asyncResult;

            try
            {
                asyncResult = (IAsyncResult)beginInvokeMethod.Invoke(channel, realParameters);
            }
            catch (TargetInvocationException tie)
            {
                if (tie.InnerException != null)
                {
                    throw tie.InnerException;
                }

                throw;
            }

            if (!asyncResult.CompletedSynchronously)
            {
                wcfAsyncResult.InnerAsyncResult = asyncResult;
            }
            return(wcfAsyncResult);
        }
        /// <summary>
        /// Submit the specified <see cref="EntityChangeSet"/> to the DomainService, with the results of the operation
        /// being returned on the SubmitCompleted event args.
        /// </summary>
        /// <param name="changeSet">The changeset to submit. If the changeset is empty, an <see cref="InvalidOperationException"/> will
        /// be thrown.</param>
        /// <param name="callback">The callback to invoke when the submit has been executed.</param>
        /// <param name="userState">Optional state that will flow through to the SubmitCompleted event</param>
        /// <returns>An asynchronous result that identifies this submit.</returns>
        /// <exception cref="InvalidOperationException">The changeset is empty.</exception>
        /// <exception cref="InvalidOperationException">The specified query does not exist.</exception>
        protected sealed override IAsyncResult BeginSubmitCore(EntityChangeSet changeSet, AsyncCallback callback, object userState)
        {
            MethodInfo beginSubmitMethod = WebDomainClient <TContract> .ResolveBeginMethod("SubmitChanges");

            MethodInfo endSubmitMethod = WebDomainClient <TContract> .ResolveEndMethod("SubmitChanges");

            IEnumerable <ChangeSetEntry> submitOperations = changeSet.GetChangeSetEntries();

            TContract channel = this.ChannelFactory.CreateChannel();
            WebDomainClientAsyncResult <TContract> wcfAsyncResult = WebDomainClientAsyncResult <TContract> .CreateSubmitResult(this, channel, endSubmitMethod, changeSet, submitOperations.ToList(), callback, userState);

            object[] parameters =
            {
                submitOperations,
                new AsyncCallback(delegate(IAsyncResult asyncResponseResult)
                {
                    wcfAsyncResult.InnerAsyncResult = asyncResponseResult;
                    wcfAsyncResult.Complete();
                }),
                userState
            };

            IAsyncResult asyncResult;

            try
            {
                asyncResult = (IAsyncResult)beginSubmitMethod.Invoke(channel, parameters);
            }
            catch (TargetInvocationException tie)
            {
                if (tie.InnerException != null)
                {
                    throw tie.InnerException;
                }

                throw;
            }

            if (!asyncResult.CompletedSynchronously)
            {
                wcfAsyncResult.InnerAsyncResult = asyncResult;
            }
            return(wcfAsyncResult);
        }
        /// <summary>
        /// Method called by the framework to begin an asynchronous query operation
        /// </summary>
        /// <param name="query">The query to invoke.</param>
        /// <param name="callback">The callback to invoke when the query has been executed.</param>
        /// <param name="userState">Optional state associated with this operation.</param>
        /// <returns>An asynchronous result that identifies this query.</returns>
        /// <exception cref="InvalidOperationException">The specified query does not exist.</exception>
        protected sealed override IAsyncResult BeginQueryCore(EntityQuery query, AsyncCallback callback, object userState)
        {
            MethodInfo beginQueryMethod = WebDomainClient <TContract> .ResolveBeginMethod(query.QueryName);

            MethodInfo endQueryMethod = WebDomainClient <TContract> .ResolveEndMethod(query.QueryName);

            // Pass query parameters.
            ParameterInfo[] parameterInfos  = beginQueryMethod.GetParameters();
            object[]        realParameters  = new object[parameterInfos.Length];
            int             parametersCount = (query.Parameters == null) ? 0 : query.Parameters.Count;

            for (int i = 0; i < parametersCount; i++)
            {
                realParameters[i] = query.Parameters[parameterInfos[i].Name];
            }

            TContract channel = this.ChannelFactory.CreateChannel();

            WebDomainClientAsyncResult <TContract> wcfAsyncResult = WebDomainClientAsyncResult <TContract> .CreateQueryResult(this, channel, endQueryMethod, callback, userState);

            // Pass async operation related parameters.
            realParameters[parameterInfos.Length - 2] = new AsyncCallback(delegate(IAsyncResult asyncResponseResult)
            {
                wcfAsyncResult.InnerAsyncResult = asyncResponseResult;
                wcfAsyncResult.Complete();
            });
            realParameters[parameterInfos.Length - 1] = userState;

            IAsyncResult asyncResult;

            try
            {
                // Pass the query as a message property.
                using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel))
                {
                    if (query.Query != null)
                    {
                        OperationContext.Current.OutgoingMessageProperties.Add(WebDomainClient <object> .QueryPropertyName, query.Query);
                    }
                    if (query.IncludeTotalCount)
                    {
                        OperationContext.Current.OutgoingMessageProperties.Add(WebDomainClient <object> .IncludeTotalCountPropertyName, true);
                    }

                    asyncResult = (IAsyncResult)beginQueryMethod.Invoke(channel, realParameters);
                }
            }
            catch (TargetInvocationException tie)
            {
                if (tie.InnerException != null)
                {
                    throw tie.InnerException;
                }

                throw;
            }

            if (!asyncResult.CompletedSynchronously)
            {
                wcfAsyncResult.InnerAsyncResult = asyncResult;
            }

            return(wcfAsyncResult);
        }