2

我想知道使用 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
}
4

0 回答 0