/// <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="cancellationToken"><see cref="CancellationToken"/> to be used for requesting cancellation</param> /// <returns>The results returned by the submit request.</returns> /// <exception cref="InvalidOperationException">The changeset is empty.</exception> protected override Task <SubmitCompletedResult> SubmitAsyncCore(EntityChangeSet changeSet, CancellationToken cancellationToken) { IEnumerable <ChangeSetEntry> submitOperations = changeSet.GetChangeSetEntries(); TContract channel = this.ChannelFactory.CreateChannel(); return(CallServiceOperation <SubmitCompletedResult>(channel, "SubmitChanges", new Dictionary <string, object>() { { "changeSet", submitOperations } }, (state, asyncResult) => { try { var returnValue = (IEnumerable <ChangeSetEntry>)EndServiceOperationCall(state, asyncResult); return new SubmitCompletedResult(changeSet, returnValue ?? Enumerable.Empty <ChangeSetEntry>()); } catch (FaultException <DomainServiceFault> fe) { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } }, cancellationToken)); }
/// <summary> /// Invokes an operation asynchronously. /// </summary> /// <param name="invokeArgs">The arguments to the Invoke operation.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> to be used for requesting cancellation</param> /// <returns>The results returned by the invocation.</returns> /// <exception cref="InvalidOperationException">The specified query does not exist.</exception> protected override Task <InvokeCompletedResult> InvokeAsyncCore(InvokeArgs invokeArgs, CancellationToken cancellationToken) { return(CallServiceOperation(invokeArgs.OperationName, invokeArgs.Parameters, (asyncResult) => { IEnumerable <ValidationResult> validationErrors = null; object returnValue = null; try { returnValue = EndServiceOperationCall(this.ChannelFactory, asyncResult); } catch (FaultException <DomainServiceFault> fe) { if (fe.Detail.OperationErrors != null) { validationErrors = fe.Detail.GetValidationErrors(); } else { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } } return new InvokeCompletedResult(returnValue, validationErrors ?? Enumerable.Empty <ValidationResult>()); }, cancellationToken)); }
/// <summary> /// Gets the results of a submit. /// </summary> /// <param name="asyncResult">An asynchronous result that identifies a submit.</param> /// <returns>The results returned by the submit.</returns> protected sealed override SubmitCompletedResult EndSubmitCore(IAsyncResult asyncResult) { WebDomainClientAsyncResult <TContract> wcfAsyncResult = this.EndAsyncResult(asyncResult, AsyncOperationType.Submit, /* cancel */ false); MethodInfo endSubmitMethod = wcfAsyncResult.EndOperationMethod; EntityChangeSet changeSet = wcfAsyncResult.EntityChangeSet; IEnumerable <ChangeSetEntry> returnValue; try { try { returnValue = (IEnumerable <ChangeSetEntry>)endSubmitMethod.Invoke(wcfAsyncResult.Channel, new object[] { wcfAsyncResult.InnerAsyncResult }); } catch (TargetInvocationException tie) { if (tie.InnerException != null) { throw tie.InnerException; } throw; } finally { ((IChannel)wcfAsyncResult.Channel).Close(); } } catch (FaultException <DomainServiceFault> fe) { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } return(new SubmitCompletedResult(changeSet, returnValue ?? Enumerable.Empty <ChangeSetEntry>())); }
/// <summary> /// Method called by the framework to begin an asynchronous query operation /// </summary> /// <param name="query">The query to invoke.</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> to be used for requesting cancellation</param> /// <returns>The results returned by the query.</returns> /// <exception cref="InvalidOperationException">The specified query does not exist.</exception> protected override Task <QueryCompletedResult> QueryAsyncCore(EntityQuery query, CancellationToken cancellationToken) { TContract channel = this.ChannelFactory.CreateChannel(); // 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); } return(CallServiceOperation <QueryCompletedResult>(channel, query.QueryName, query.Parameters, (state, asyncResult) => { IEnumerable <ValidationResult> validationErrors = null; QueryResult returnValue = null; try { returnValue = (QueryResult)EndServiceOperationCall(state, asyncResult); } catch (FaultException <DomainServiceFault> fe) { if (fe.Detail.OperationErrors != null) { validationErrors = fe.Detail.GetValidationErrors(); } else { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } } if (returnValue != null) { return new QueryCompletedResult( returnValue.GetRootResults().Cast <Entity>(), returnValue.GetIncludedResults().Cast <Entity>(), returnValue.TotalCount, Enumerable.Empty <ValidationResult>()); } else { return new QueryCompletedResult( Enumerable.Empty <Entity>(), Enumerable.Empty <Entity>(), /* totalCount */ 0, validationErrors ?? Enumerable.Empty <ValidationResult>()); } } , cancellationToken)); } }
/// <summary> /// Calls an operation on an already constructed WCF service channel /// </summary> /// <typeparam name="TResult"></typeparam> /// <param name="operationName">name of method/operation to call</param> /// <param name="parameters">parameters for the call</param> /// <param name="callback">callback responsible for casting return value and epr method error handling</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> to be used for requesting cancellation</param> /// <returns>A <see cref="Task{TResult}"/> which will contain the result of the operation, exception or be cancelled</returns> protected virtual Task <TResult> CallServiceOperation <TResult>(string operationName, IDictionary <string, object> parameters, Func <IAsyncResult, TResult> callback, CancellationToken cancellationToken) { MethodInfo beginInvokeMethod = WebDomainClient <TContract> .ResolveBeginMethod(operationName); MethodInfo endInvokeMethod = WebDomainClient <TContract> .ResolveEndMethod(operationName); var taskCompletionSource = new TaskCompletionSource <TResult>(); if (parameters == null) { parameters = new Dictionary <string, object>(2); } // Pass async operation related parameters. parameters.Add("callback", new AsyncCallback(delegate(IAsyncResult asyncResponseResult) { try { TResult result = callback(asyncResponseResult); taskCompletionSource.SetResult(result); } #pragma warning disable CA1031 // Do not catch general exception types, we "rethrow it via task catch (CommunicationException) when(cancellationToken.IsCancellationRequested) { taskCompletionSource.TrySetCanceled(cancellationToken); } catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { taskCompletionSource.TrySetException(ex); } })); parameters.Add("asyncState", /*userState*/ endInvokeMethod); // Call Begin** method // Handle any immediate CommunicationException which can be thrown directly from begin method // for some tests that perform invalid calls against localhost try { InvokeBeginMethod(beginInvokeMethod, ChannelFactory, parameters); } catch (CommunicationException ex) { // We might have aborted the channel due to cancellation if (cancellationToken.IsCancellationRequested) { taskCompletionSource.TrySetCanceled(cancellationToken); } else { taskCompletionSource.TrySetException(ex); } } return(taskCompletionSource.Task); }
/// <summary> /// Gets the results of a query. /// </summary> /// <param name="asyncResult">An asynchronous result that identifies a query.</param> /// <returns>The results returned by the query.</returns> protected sealed override QueryCompletedResult EndQueryCore(IAsyncResult asyncResult) { WebDomainClientAsyncResult <TContract> wcfAsyncResult = this.EndAsyncResult(asyncResult, AsyncOperationType.Query, /* cancel */ false); MethodInfo endQueryMethod = (MethodInfo)wcfAsyncResult.EndOperationMethod; IEnumerable <ValidationResult> validationErrors = null; QueryResult returnValue = null; try { try { returnValue = (QueryResult)endQueryMethod.Invoke(wcfAsyncResult.Channel, new object[] { wcfAsyncResult.InnerAsyncResult }); } catch (TargetInvocationException tie) { if (tie.InnerException != null) { throw tie.InnerException; } throw; } finally { ((IChannel)wcfAsyncResult.Channel).Close(); } } catch (FaultException <DomainServiceFault> fe) { if (fe.Detail.OperationErrors != null) { validationErrors = fe.Detail.GetValidationErrors(); } else { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } } if (returnValue != null) { return(new QueryCompletedResult( returnValue.GetRootResults().Cast <Entity>(), returnValue.GetIncludedResults().Cast <Entity>(), returnValue.TotalCount, Enumerable.Empty <ValidationResult>())); } else { return(new QueryCompletedResult( new Entity[0], new Entity[0], /* totalCount */ 0, validationErrors ?? Enumerable.Empty <ValidationResult>())); } }
/// <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> /// Initializes a new <see cref="WebDomainClientAsyncResult<TContract>"/> instance used for Invoke operations. /// </summary> /// <param name="domainClient">The <see cref="WebDomainClient<TContract>"/> associated with this result.</param> /// <param name="channel">The channel used to communicate with the server.</param> /// <param name="endOperationMethod">The method that completes an asynchronous operation.</param> /// <param name="invokeArgs">The arguments to the Invoke operation.</param> /// <param name="callback">Optional <see cref="AsyncCallback"/> to invoke upon completion.</param> /// <param name="asyncState">Optional user state information that will be passed to the <paramref name="callback"/>.</param> /// <exception cref="ArgumentNullException">if <paramref name="domainClient"/> is null.</exception> /// <exception cref="ArgumentNullException">if <paramref name="endOperationMethod"/> is null.</exception> private WebDomainClientAsyncResult(WebDomainClient <TContract> domainClient, TContract channel, MethodInfo endOperationMethod, InvokeArgs invokeArgs, AsyncCallback callback, object asyncState) : base(domainClient, invokeArgs, callback, asyncState) { if (channel == null) { throw new ArgumentNullException("channel"); } if (endOperationMethod == null) { throw new ArgumentNullException("endOperationMethod"); } this._endOperationMethod = endOperationMethod; this._channel = channel; }
/// <summary> /// Initializes a new <see cref="WebDomainClientAsyncResult<TContract>"/> instance used for Submit operations. /// </summary> /// <param name="domainClient">The <see cref="WebDomainClient<TContract>"/> associated with this result.</param> /// <param name="channel">The channel used to communicate with the server.</param> /// <param name="endOperationMethod">The method that completes an asynchronous operation.</param> /// <param name="entityChangeSet">The Submit operation <see cref="EntityChangeSet"/>.</param> /// <param name="changeSetEntries">The collection of <see cref="ChangeSetEntry"/>s to submit.</param> /// <param name="callback">Optional <see cref="AsyncCallback"/> to invoke upon completion.</param> /// <param name="asyncState">Optional user state information that will be passed to the <paramref name="callback"/>.</param> /// <exception cref="ArgumentNullException">if <paramref name="domainClient"/> is null.</exception> /// <exception cref="ArgumentNullException">if <paramref name="endOperationMethod"/> is null.</exception> private WebDomainClientAsyncResult(WebDomainClient <TContract> domainClient, TContract channel, MethodInfo endOperationMethod, EntityChangeSet entityChangeSet, IEnumerable <ChangeSetEntry> changeSetEntries, AsyncCallback callback, object asyncState) : base(domainClient, entityChangeSet, callback, asyncState) { if (channel == null) { throw new ArgumentNullException("channel"); } if (endOperationMethod == null) { throw new ArgumentNullException("endOperationMethod"); } this._endOperationMethod = endOperationMethod; this._channel = channel; this._changeSetEntries = changeSetEntries; }
/// <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="cancellationToken"><see cref="CancellationToken"/> to be used for requesting cancellation</param> /// <returns>The results returned by the query.</returns> /// <exception cref="InvalidOperationException">The specified query does not exist.</exception> protected override Task <QueryCompletedResult> QueryAsyncCore(EntityQuery query, CancellationToken cancellationToken) { return(CallServiceOperation <QueryCompletedResult>(query.QueryName, query.Parameters, (asyncResult) => { IEnumerable <ValidationResult> validationErrors = null; QueryResult returnValue = null; try { returnValue = (QueryResult)EndServiceOperationCall(this.ChannelFactory, asyncResult); } catch (FaultException <DomainServiceFault> fe) { if (fe.Detail.OperationErrors != null) { validationErrors = fe.Detail.GetValidationErrors(); } else { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } } if (returnValue != null) { return new QueryCompletedResult( returnValue.GetRootResults().Cast <Entity>(), returnValue.GetIncludedResults().Cast <Entity>(), returnValue.TotalCount, Enumerable.Empty <ValidationResult>()); } else { return new QueryCompletedResult( Enumerable.Empty <Entity>(), Enumerable.Empty <Entity>(), /* totalCount */ 0, validationErrors ?? Enumerable.Empty <ValidationResult>()); } } , cancellationToken)); }
/// <summary> /// Gets the results of an invocation. /// </summary> /// <param name="asyncResult">An asynchronous result that identifies an invocation.</param> /// <returns>The results returned by the invocation.</returns> protected sealed override InvokeCompletedResult EndInvokeCore(IAsyncResult asyncResult) { WebDomainClientAsyncResult <TContract> wcfAsyncResult = this.EndAsyncResult(asyncResult, AsyncOperationType.Invoke, /* cancel */ false); MethodInfo endInvokeMethod = (MethodInfo)wcfAsyncResult.EndOperationMethod; IEnumerable <ValidationResult> validationErrors = null; object returnValue = null; try { try { returnValue = endInvokeMethod.Invoke(wcfAsyncResult.Channel, new object[] { wcfAsyncResult.InnerAsyncResult }); } catch (TargetInvocationException tie) { if (tie.InnerException != null) { throw tie.InnerException; } throw; } finally { ((IChannel)wcfAsyncResult.Channel).Close(); } } catch (FaultException <DomainServiceFault> fe) { if (fe.Detail.OperationErrors != null) { validationErrors = fe.Detail.GetValidationErrors(); } else { throw WebDomainClient <TContract> .GetExceptionFromServiceFault(fe.Detail); } } return(new InvokeCompletedResult(returnValue, validationErrors ?? Enumerable.Empty <ValidationResult>())); }
/// <summary> /// Calls an operation on an already constructed WCF service channel /// </summary> /// <typeparam name="TResult"></typeparam> /// <param name="channel">WCF channel</param> /// <param name="operationName">name of method/operation to call</param> /// <param name="parameters">parameters for the call</param> /// <param name="callback">callback responsible for casting return value and epr method error handling</param> /// <param name="cancellationToken"><see cref="CancellationToken"/> to be used for requesting cancellation</param> /// <returns>A <see cref="Task{TResult}"/> which will contain the result of the operation, exception or be cancelled</returns> protected virtual Task <TResult> CallServiceOperation <TResult>(TContract channel, string operationName, IDictionary <string, object> parameters, Func <object, IAsyncResult, TResult> callback, CancellationToken cancellationToken) { MethodInfo beginInvokeMethod = WebDomainClient <TContract> .ResolveBeginMethod(operationName); MethodInfo endInvokeMethod = WebDomainClient <TContract> .ResolveEndMethod(operationName); // Pass operation parameters. ParameterInfo[] parameterInfos = beginInvokeMethod.GetParameters(); object[] realParameters = new object[parameterInfos.Length]; int parametersCount = parameters == null ? 0 : parameters.Count; for (int i = 0; i < parametersCount; i++) { realParameters[i] = parameters[parameterInfos[i].Name]; } var taskCompletionSource = new TaskCompletionSource <TResult>(); CancellationTokenRegistration cancellationTokenRegistration = default; if (cancellationToken.CanBeCanceled) { cancellationTokenRegistration = cancellationToken.Register(state => { ((IChannel)state).Abort(); }, channel); } // Pass async operation related parameters. realParameters[realParameters.Length - 2] = new AsyncCallback(delegate(IAsyncResult asyncResponseResult) { cancellationTokenRegistration.Dispose(); try { TResult result = callback(channel, asyncResponseResult); taskCompletionSource.SetResult(result); } catch (CommunicationException) when(cancellationToken.IsCancellationRequested) { #if SILVERLIGHT || NET45 taskCompletionSource.SetCanceled(); #else taskCompletionSource.TrySetCanceled(cancellationToken); #endif } #pragma warning disable CA1031 // Do not catch general exception types, we "rethrow it via task catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { taskCompletionSource.SetException(ex); } finally { if (((IChannel)channel).State == CommunicationState.Faulted) { ((IChannel)channel).Abort(); } else { ((IChannel)channel).Close(); } } }); realParameters[realParameters.Length - 1] = /*userState*/ endInvokeMethod; // Call Begin** method InvokeMethod(beginInvokeMethod, channel, realParameters); return(taskCompletionSource.Task); }
/// <summary> /// Creates a new <see cref="WebDomainClientAsyncResult<TContract>"/> used for Invoke operations. /// </summary> /// <param name="domainClient">The <see cref="WebDomainClient<TContract>"/> associated with this result.</param> /// <param name="channel">The channel used to communicate with the server.</param> /// <param name="endOperationMethod">The method that completes an asynchronous operation.</param> /// <param name="invokeArgs">The arguments to the Invoke operation.</param> /// <param name="callback">The <see cref="AsyncCallback"/> to invoke upon completion.</param> /// <param name="asyncState">Optional user state information that will be passed to the <paramref name="callback"/>.</param> /// <returns>A <see cref="WebDomainClientAsyncResult<TContract>"/> used for Invoke operations</returns> public static WebDomainClientAsyncResult <TContract> CreateInvokeResult(WebDomainClient <TContract> domainClient, TContract channel, MethodInfo endOperationMethod, InvokeArgs invokeArgs, AsyncCallback callback, object asyncState) { return(new WebDomainClientAsyncResult <TContract>(domainClient, channel, endOperationMethod, invokeArgs, callback, asyncState)); }
/// <summary> /// Creates a new <see cref="WebDomainClientAsyncResult<TContract>"/> used for Submit operations. /// </summary> /// <param name="domainClient">The <see cref="WebDomainClient<TContract>"/> associated with this result.</param> /// <param name="channel">The channel used to communicate with the server.</param> /// <param name="endOperationMethod">The method that completes an asynchronous operation.</param> /// <param name="entityChangeSet">The Submit operation <see cref="EntityChangeSet"/>.</param> /// <param name="changeSetEntries">The collection of <see cref="ChangeSetEntry"/>s to submit.</param> /// <param name="callback">The <see cref="AsyncCallback"/> to invoke upon completion.</param> /// <param name="asyncState">Optional user state information that will be passed to the <paramref name="callback"/>.</param> /// <returns>A <see cref="WebDomainClientAsyncResult<TContract>"/> used for Submit operations</returns> public static WebDomainClientAsyncResult <TContract> CreateSubmitResult(WebDomainClient <TContract> domainClient, TContract channel, MethodInfo endOperationMethod, EntityChangeSet entityChangeSet, IEnumerable <ChangeSetEntry> changeSetEntries, AsyncCallback callback, object asyncState) { return(new WebDomainClientAsyncResult <TContract>(domainClient, channel, endOperationMethod, entityChangeSet, changeSetEntries, callback, asyncState)); }
/// <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); }