204 lines
7.6 KiB
C#
204 lines
7.6 KiB
C#
|
//----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Channels
|
||
|
{
|
||
|
using System.Runtime;
|
||
|
using System.ServiceModel;
|
||
|
|
||
|
class ReliableChannelFactory<TChannel, InnerChannel> : ChannelFactoryBase<TChannel>, IReliableFactorySettings
|
||
|
where InnerChannel : class, IChannel
|
||
|
{
|
||
|
TimeSpan acknowledgementInterval;
|
||
|
FaultHelper faultHelper;
|
||
|
bool flowControlEnabled;
|
||
|
TimeSpan inactivityTimeout;
|
||
|
int maxPendingChannels;
|
||
|
int maxRetryCount;
|
||
|
int maxTransferWindowSize;
|
||
|
MessageVersion messageVersion;
|
||
|
bool ordered;
|
||
|
ReliableMessagingVersion reliableMessagingVersion;
|
||
|
|
||
|
IChannelFactory<InnerChannel> innerChannelFactory;
|
||
|
|
||
|
public ReliableChannelFactory(ReliableSessionBindingElement settings, IChannelFactory<InnerChannel> innerChannelFactory, Binding binding)
|
||
|
: base(binding)
|
||
|
{
|
||
|
this.acknowledgementInterval = settings.AcknowledgementInterval;
|
||
|
this.flowControlEnabled = settings.FlowControlEnabled;
|
||
|
this.inactivityTimeout = settings.InactivityTimeout;
|
||
|
this.maxPendingChannels = settings.MaxPendingChannels;
|
||
|
this.maxRetryCount = settings.MaxRetryCount;
|
||
|
this.maxTransferWindowSize = settings.MaxTransferWindowSize;
|
||
|
this.messageVersion = binding.MessageVersion;
|
||
|
this.ordered = settings.Ordered;
|
||
|
this.reliableMessagingVersion = settings.ReliableMessagingVersion;
|
||
|
|
||
|
this.innerChannelFactory = innerChannelFactory;
|
||
|
this.faultHelper = new SendFaultHelper(binding.SendTimeout, binding.CloseTimeout);
|
||
|
}
|
||
|
|
||
|
public TimeSpan AcknowledgementInterval
|
||
|
{
|
||
|
get { return this.acknowledgementInterval; }
|
||
|
}
|
||
|
|
||
|
public FaultHelper FaultHelper
|
||
|
{
|
||
|
get { return this.faultHelper; }
|
||
|
}
|
||
|
|
||
|
public bool FlowControlEnabled
|
||
|
{
|
||
|
get { return this.flowControlEnabled; }
|
||
|
}
|
||
|
|
||
|
public TimeSpan InactivityTimeout
|
||
|
{
|
||
|
get { return this.inactivityTimeout; }
|
||
|
}
|
||
|
|
||
|
protected IChannelFactory<InnerChannel> InnerChannelFactory
|
||
|
{
|
||
|
get { return this.innerChannelFactory; }
|
||
|
}
|
||
|
|
||
|
public int MaxPendingChannels
|
||
|
{
|
||
|
get { return this.maxPendingChannels; }
|
||
|
}
|
||
|
|
||
|
public int MaxRetryCount
|
||
|
{
|
||
|
get { return this.maxRetryCount; }
|
||
|
}
|
||
|
|
||
|
public MessageVersion MessageVersion
|
||
|
{
|
||
|
get { return this.messageVersion; }
|
||
|
}
|
||
|
|
||
|
public int MaxTransferWindowSize
|
||
|
{
|
||
|
get { return this.maxTransferWindowSize; }
|
||
|
}
|
||
|
|
||
|
public bool Ordered
|
||
|
{
|
||
|
get { return this.ordered; }
|
||
|
}
|
||
|
|
||
|
public ReliableMessagingVersion ReliableMessagingVersion
|
||
|
{
|
||
|
get { return this.reliableMessagingVersion; }
|
||
|
}
|
||
|
|
||
|
public override T GetProperty<T>()
|
||
|
{
|
||
|
if (typeof(T) == typeof(IChannelFactory<TChannel>))
|
||
|
{
|
||
|
return (T)(object)this;
|
||
|
}
|
||
|
|
||
|
T baseProperty = base.GetProperty<T>();
|
||
|
if (baseProperty != null)
|
||
|
{
|
||
|
return baseProperty;
|
||
|
}
|
||
|
|
||
|
return this.innerChannelFactory.GetProperty<T>();
|
||
|
}
|
||
|
|
||
|
public TimeSpan SendTimeout
|
||
|
{
|
||
|
get { return this.InternalSendTimeout; }
|
||
|
}
|
||
|
|
||
|
protected override void OnAbort()
|
||
|
{
|
||
|
// Aborting base first to abort channels. Must abort higher channels before aborting lower channels.
|
||
|
base.OnAbort();
|
||
|
this.faultHelper.Abort();
|
||
|
this.innerChannelFactory.Abort();
|
||
|
}
|
||
|
|
||
|
protected override void OnOpen(TimeSpan timeout)
|
||
|
{
|
||
|
this.innerChannelFactory.Open(timeout);
|
||
|
}
|
||
|
|
||
|
protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
|
||
|
{
|
||
|
return this.innerChannelFactory.BeginOpen(callback, state);
|
||
|
}
|
||
|
|
||
|
protected override void OnEndOpen(IAsyncResult result)
|
||
|
{
|
||
|
this.innerChannelFactory.EndOpen(result);
|
||
|
}
|
||
|
|
||
|
protected override void OnClose(TimeSpan timeout)
|
||
|
{
|
||
|
TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
|
||
|
// Closing base first to close channels. Must close higher channels before closing lower channels.
|
||
|
base.OnClose(timeoutHelper.RemainingTime());
|
||
|
this.faultHelper.Close(timeoutHelper.RemainingTime());
|
||
|
this.innerChannelFactory.Close(timeoutHelper.RemainingTime());
|
||
|
}
|
||
|
|
||
|
protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
|
||
|
{
|
||
|
// Closing base first to close channels. Must close higher channels before closing lower channels.
|
||
|
return OperationWithTimeoutComposer.BeginComposeAsyncOperations(
|
||
|
timeout,
|
||
|
new OperationWithTimeoutBeginCallback[]
|
||
|
{
|
||
|
new OperationWithTimeoutBeginCallback(base.OnBeginClose),
|
||
|
new OperationWithTimeoutBeginCallback(this.faultHelper.BeginClose),
|
||
|
new OperationWithTimeoutBeginCallback(this.innerChannelFactory.BeginClose)
|
||
|
},
|
||
|
new OperationEndCallback[]
|
||
|
{
|
||
|
new OperationEndCallback(base.OnEndClose),
|
||
|
new OperationEndCallback(this.faultHelper.EndClose),
|
||
|
new OperationEndCallback(this.innerChannelFactory.EndClose)
|
||
|
},
|
||
|
callback,
|
||
|
state);
|
||
|
}
|
||
|
|
||
|
protected override void OnEndClose(IAsyncResult result)
|
||
|
{
|
||
|
OperationWithTimeoutComposer.EndComposeAsyncOperations(result);
|
||
|
}
|
||
|
|
||
|
protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
|
||
|
{
|
||
|
LateBoundChannelParameterCollection channelParameters = new LateBoundChannelParameterCollection();
|
||
|
|
||
|
IClientReliableChannelBinder binder = ClientReliableChannelBinder<InnerChannel>.CreateBinder(address, via,
|
||
|
this.InnerChannelFactory, MaskingMode.All,
|
||
|
TolerateFaultsMode.IfNotSecuritySession, channelParameters, this.DefaultCloseTimeout,
|
||
|
this.DefaultSendTimeout);
|
||
|
|
||
|
if (typeof(TChannel) == typeof(IOutputSessionChannel))
|
||
|
{
|
||
|
if (typeof(InnerChannel) == typeof(IDuplexChannel) || typeof(InnerChannel) == typeof(IDuplexSessionChannel))
|
||
|
return (TChannel)(object)new ReliableOutputSessionChannelOverDuplex(this, this, binder, this.faultHelper, channelParameters);
|
||
|
|
||
|
// typeof(InnerChannel) == typeof(IRequestChannel) || typeof(InnerChannel) == typeof(IRequestSessionChannel))
|
||
|
return (TChannel)(object)new ReliableOutputSessionChannelOverRequest(this, this, binder, this.faultHelper, channelParameters);
|
||
|
}
|
||
|
else if (typeof(TChannel) == typeof(IDuplexSessionChannel))
|
||
|
{
|
||
|
return (TChannel)(object)new ClientReliableDuplexSessionChannel(this, this, binder, this.faultHelper, channelParameters, WsrmUtilities.NextSequenceId());
|
||
|
}
|
||
|
|
||
|
// (typeof(TChannel) == typeof(IRequestSessionChannel)
|
||
|
return (TChannel)(object)new ReliableRequestSessionChannel(this, this, binder, this.faultHelper, channelParameters, WsrmUtilities.NextSequenceId());
|
||
|
}
|
||
|
}
|
||
|
}
|