Как каналы, созданные с помощью ChannelFactory, могут быть преобразованы в ICommunicationObject?
Интересно, как T-каналы, созданные с помощью ChannelFactory, могут быть преобразованы в ICommunicationObject?
Я спрашиваю об этом потому, что я начал писать простой ChannelProxy для управления ошибочным состоянием и автоматического воссоздания другого канала. Когда я получаю свой экземпляр интерфейса через GetTransparentProxy (), я не могу привести его к ICommunicationObject. Я думаю, что мой конструктор должен переопределить базу (typeof(T+ICommunicationObject)) вместо только base(typeof(T))... но как?
Вот мой исходный код: не завершен, не полностью прокомментирован и не протестирован;)
public class ChannelProxy<T> : RealProxy, ICommunicationObject
where T : class
{
public ChannelProxy(Func<T> factory)
: base(typeof(T))
{
_factory = factory;
Retries = 3;
}
private int Retries { get; set; }
private Func<T> _factory;
private RealProxy _innerChannelProxy;
private ICommunicationObject _innerChannel;
public override IMessage Invoke(IMessage msg)
{
int attempt = 0;
while (true)
{
// Ensure channel is open
if (!IsInnerChannelUsable())
{
CloseInnerChannel();
OpenInnerChannel();
}
// Call Channel method
var result = _innerChannelProxy.Invoke(msg) as ReturnMessage;
// Everything ok
if (result.Exception == null)
return result;
// Not an communication exception
if (!(result.Exception is CommunicationException))
return result;
// Max retries reach
if (attempt >= Retries)
return result;
attempt++;
}
}
private void OpenInnerChannel()
{
try
{
if (_innerChannel == null)
{
// Recreate WCF channel
_innerChannel = _factory() as ICommunicationObject;
_innerChannelProxy = RemotingServices.GetRealProxy(_innerChannel);
}
}
catch (Exception)
{
// TODO
}
}
private void CloseInnerChannel()
{
try
{
if (_innerChannel != null)
{
try
{
_innerChannel.Close();
}
catch (CommunicationException)
{
_innerChannel.Abort();
}
catch (TimeoutException)
{
_innerChannel.Abort();
}
catch (Exception)
{
_innerChannel.Abort();
}
}
}
catch (Exception)
{
// TODO
int toto = 0;
}
finally
{
_innerChannel = null;
_innerChannelProxy = null;
}
}
bool IsInnerChannelUsable()
{
if (_innerChannel == null)
return false;
var state = _innerChannel.State;
return state == CommunicationState.Opened || state == CommunicationState.Created;
}
#region ICommunicationObject
public void Abort()
{
if (_innerChannel != null)
_innerChannel.Abort();
}
public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
{
if (_innerChannel != null)
return _innerChannel.BeginClose(timeout, callback, state);
var fn = new Func<bool>(() => true);
return fn.BeginInvoke(callback, state);
}
public IAsyncResult BeginClose(AsyncCallback callback, object state)
{
if (_innerChannel != null)
return _innerChannel.BeginClose(callback, state);
var fn = new Func<bool>(() => true);
return fn.BeginInvoke(callback, state);
}
public IAsyncResult BeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
{
if (_innerChannel != null)
return _innerChannel.BeginOpen(timeout, callback, state);
var fn = new Func<bool>(() => true);
return fn.BeginInvoke(callback, state);
}
public IAsyncResult BeginOpen(AsyncCallback callback, object state)
{
if (_innerChannel != null)
return _innerChannel.BeginOpen(callback, state);
var fn = new Func<bool>(() => true);
return fn.BeginInvoke(callback, state);
}
public void Close(TimeSpan timeout)
{
if (_innerChannel != null)
_innerChannel.Close(timeout);
}
public void Close()
{
if (_innerChannel != null)
_innerChannel.Close();
}
public event EventHandler Closed;
public event EventHandler Closing;
public void EndClose(IAsyncResult result)
{
if (_innerChannel != null)
_innerChannel.EndClose(result);
}
public void EndOpen(IAsyncResult result)
{
if (_innerChannel != null)
_innerChannel.EndOpen(result);
}
public event EventHandler Faulted;
public void Open(TimeSpan timeout)
{
if (_innerChannel != null)
_innerChannel.Open(timeout);
}
public void Open()
{
if (_innerChannel != null)
_innerChannel.Open();
}
public event EventHandler Opened;
public event EventHandler Opening;
public CommunicationState State
{
get { return _innerChannel == null ? CommunicationState.Closed : _innerChannel.State; }
}
#endregion
}