Как каналы, созданные с помощью 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
}

0 ответов

Другие вопросы по тегам