我想知道使用 ChannelFactory 创建的 T 通道如何转换为 ICommunicationObject?
我问这个的原因是因为我开始编写一个简单的 ChannelProxy 来管理故障状态,并自动重新创建另一个通道。当我通过 GetTransparentProxy() 获取我的接口实例时,我无法将其转换为 ICommunicationObject。我认为我的构造函数应该覆盖 base(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
}