| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268 |
- //------------------------------------------------------------
- // Copyright (c) Microsoft Corporation. All rights reserved.
- //------------------------------------------------------------
- namespace System.ServiceModel.Channels
- {
- using System;
- using System.Runtime;
- using System.ServiceModel;
- abstract class ContextOutputChannelBase<TChannel> : LayeredChannel<TChannel> where TChannel : class, IOutputChannel
- {
- protected ContextOutputChannelBase(ChannelManagerBase channelManager, TChannel innerChannel)
- : base(channelManager, innerChannel)
- {
- }
- public EndpointAddress RemoteAddress
- {
- get { return this.InnerChannel.RemoteAddress; }
- }
- public Uri Via
- {
- get { return this.InnerChannel.Via; }
- }
- protected abstract ContextProtocol ContextProtocol
- {
- get;
- }
- protected abstract bool IsClient
- {
- get;
- }
- public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
- {
- return new SendAsyncResult(message, this, this.ContextProtocol, timeout, callback, state);
- }
- public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
- {
- return this.BeginSend(message, this.DefaultSendTimeout, callback, state);
- }
- public void EndSend(IAsyncResult result)
- {
- SendAsyncResult.End(result);
- }
- public override T GetProperty<T>()
- {
- if (typeof(T) == typeof(IContextManager))
- {
- return (T)(object)this.ContextProtocol;
- }
- else
- {
- return base.GetProperty<T>();
- }
- }
- public void Send(Message message, TimeSpan timeout)
- {
- CorrelationCallbackMessageProperty callback = null;
- TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
- Message sendMessage = message;
- if (message != null)
- {
- this.ContextProtocol.OnOutgoingMessage(message, null);
- if (CorrelationCallbackMessageProperty.TryGet(message, out callback))
- {
- ContextExchangeCorrelationHelper.AddOutgoingCorrelationCallbackData(callback, message, this.IsClient);
- if (callback.IsFullyDefined)
- {
- sendMessage = callback.FinalizeCorrelation(message, timeoutHelper.RemainingTime());
- }
- }
- }
- try
- {
- this.InnerChannel.Send(sendMessage, timeoutHelper.RemainingTime());
- }
- finally
- {
- if (message != null && !object.ReferenceEquals(message, sendMessage))
- {
- sendMessage.Close();
- }
- }
- }
- public void Send(Message message)
- {
- this.Send(message, this.DefaultSendTimeout);
- }
- class SendAsyncResult : AsyncResult
- {
- static AsyncCallback onFinalizeCorrelation = Fx.ThunkCallback(new AsyncCallback(OnFinalizeCorrelationCompletedCallback));
- static AsyncCallback onSend = Fx.ThunkCallback(new AsyncCallback(OnSendCompletedCallback));
- ContextOutputChannelBase<TChannel> channel;
- CorrelationCallbackMessageProperty correlationCallback;
- Message message;
- Message sendMessage;
- TimeoutHelper timeoutHelper;
- public SendAsyncResult(Message message, ContextOutputChannelBase<TChannel> channel, ContextProtocol contextProtocol,
- TimeSpan timeout, AsyncCallback callback, object state)
- : base(callback, state)
- {
- this.channel = channel;
- this.message = this.sendMessage = message;
- this.timeoutHelper = new TimeoutHelper(timeout);
- bool shouldSend = true;
- if (message != null)
- {
- contextProtocol.OnOutgoingMessage(message, null);
- if (CorrelationCallbackMessageProperty.TryGet(message, out this.correlationCallback))
- {
- ContextExchangeCorrelationHelper.AddOutgoingCorrelationCallbackData(this.correlationCallback, message, this.channel.IsClient);
- if (this.correlationCallback.IsFullyDefined)
- {
- IAsyncResult result = this.correlationCallback.BeginFinalizeCorrelation(this.message, this.timeoutHelper.RemainingTime(), onFinalizeCorrelation, this);
- if (result.CompletedSynchronously)
- {
- if (OnFinalizeCorrelationCompleted(result))
- {
- base.Complete(true);
- }
- }
- shouldSend = false;
- }
- }
- }
- if (shouldSend)
- {
- IAsyncResult result = this.channel.InnerChannel.BeginSend(
- this.message, this.timeoutHelper.RemainingTime(), onSend, this);
- if (result.CompletedSynchronously)
- {
- OnSendCompleted(result);
- base.Complete(true);
- }
- }
- }
- public static void End(IAsyncResult result)
- {
- SendAsyncResult thisPtr = AsyncResult.End<SendAsyncResult>(result);
- }
- static void OnFinalizeCorrelationCompletedCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState;
- Exception completionException = null;
- bool completeSelf;
- try
- {
- completeSelf = thisPtr.OnFinalizeCorrelationCompleted(result);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- completeSelf = true;
- }
- if (completeSelf)
- {
- thisPtr.Complete(false, completionException);
- }
- }
- static void OnSendCompletedCallback(IAsyncResult result)
- {
- if (result.CompletedSynchronously)
- {
- return;
- }
- SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState;
- Exception completionException = null;
- try
- {
- thisPtr.OnSendCompleted(result);
- }
- catch (Exception e)
- {
- if (Fx.IsFatal(e))
- {
- throw;
- }
- completionException = e;
- }
- thisPtr.Complete(false, completionException);
- }
- bool OnFinalizeCorrelationCompleted(IAsyncResult result)
- {
- this.sendMessage = this.correlationCallback.EndFinalizeCorrelation(result);
- bool throwing = true;
- IAsyncResult sendResult;
- try
- {
- sendResult = this.channel.InnerChannel.BeginSend(
- this.sendMessage, this.timeoutHelper.RemainingTime(), onSend, this);
- throwing = false;
- }
- finally
- {
- if (throwing)
- {
- if (this.message != null && !object.ReferenceEquals(this.message, this.sendMessage))
- {
- this.sendMessage.Close();
- }
- }
- }
- if (sendResult.CompletedSynchronously)
- {
- OnSendCompleted(sendResult);
- return true;
- }
- return false;
- }
- void OnSendCompleted(IAsyncResult result)
- {
- try
- {
- this.channel.InnerChannel.EndSend(result);
- }
- finally
- {
- if (this.message != null && !object.ReferenceEquals(this.message, this.sendMessage))
- {
- this.sendMessage.Close();
- }
- }
- }
- }
- }
- }
|