1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203
|
//----------------------------------------------------------------------------
// 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());
}
}
}
|