File: FrameworkFork\System.ServiceModel\System\ServiceModel\Channels\ChannelFactoryBase.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Runtime;
using System.Threading.Tasks;
 
namespace System.ServiceModel.Channels
{
    public abstract class ChannelFactoryBase : ChannelManagerBase, IChannelFactory
    {
        private TimeSpan _closeTimeout = ServiceDefaults.CloseTimeout;
        private TimeSpan _openTimeout = ServiceDefaults.OpenTimeout;
        private TimeSpan _receiveTimeout = ServiceDefaults.ReceiveTimeout;
        private TimeSpan _sendTimeout = ServiceDefaults.SendTimeout;
 
        protected ChannelFactoryBase()
        {
        }
 
        protected ChannelFactoryBase(IDefaultCommunicationTimeouts timeouts)
        {
            this.InitializeTimeouts(timeouts);
        }
 
        protected override TimeSpan DefaultCloseTimeout
        {
            get { return _closeTimeout; }
        }
 
        protected override TimeSpan DefaultOpenTimeout
        {
            get { return _openTimeout; }
        }
 
        protected override TimeSpan DefaultReceiveTimeout
        {
            get { return _receiveTimeout; }
        }
 
        protected override TimeSpan DefaultSendTimeout
        {
            get { return _sendTimeout; }
        }
 
        public virtual T GetProperty<T>()
            where T : class
        {
            if (typeof(T) == typeof(IChannelFactory))
            {
                return (T)(object)this;
            }
 
            return default(T);
        }
 
        protected override void OnAbort()
        {
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CompletedAsyncResult(callback, state);
        }
 
        protected internal override Task OnCloseAsync(TimeSpan timeout)
        {
            return TaskHelpers.CompletedTask();
        }
 
        protected override void OnClose(TimeSpan timeout)
        {
        }
 
        protected override void OnEndClose(IAsyncResult result)
        {
            CompletedAsyncResult.End(result);
        }
 
        private void InitializeTimeouts(IDefaultCommunicationTimeouts timeouts)
        {
            if (timeouts != null)
            {
                _closeTimeout = timeouts.CloseTimeout;
                _openTimeout = timeouts.OpenTimeout;
                _receiveTimeout = timeouts.ReceiveTimeout;
                _sendTimeout = timeouts.SendTimeout;
            }
        }
    }
 
    public abstract class ChannelFactoryBase<TChannel> : ChannelFactoryBase, IChannelFactory<TChannel>
    {
        private CommunicationObjectManager<IChannel> _channels;
 
        protected ChannelFactoryBase()
            : this(null)
        {
        }
 
        protected ChannelFactoryBase(IDefaultCommunicationTimeouts timeouts)
            : base(timeouts)
        {
            _channels = new CommunicationObjectManager<IChannel>(this.ThisLock);
        }
 
        public TChannel CreateChannel(EndpointAddress address)
        {
            if (address == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
 
            return this.InternalCreateChannel(address, address.Uri);
        }
 
        public TChannel CreateChannel(EndpointAddress address, Uri via)
        {
            if (address == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("address");
 
            if (via == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("via");
 
            return this.InternalCreateChannel(address, via);
        }
 
        private TChannel InternalCreateChannel(EndpointAddress address, Uri via)
        {
            this.ValidateCreateChannel();
            TChannel channel = this.OnCreateChannel(address, via);
 
            bool success = false;
 
            try
            {
                _channels.Add((IChannel)(object)channel);
                success = true;
            }
            finally
            {
                if (!success)
                    ((IChannel)(object)channel).Abort();
            }
 
            return channel;
        }
 
        protected abstract TChannel OnCreateChannel(EndpointAddress address, Uri via);
 
        protected void ValidateCreateChannel()
        {
            ThrowIfDisposed();
            if (this.State != CommunicationState.Opened)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(string.Format(SRServiceModel.ChannelFactoryCannotBeUsedToCreateChannels, this.GetType().ToString())));
            }
        }
 
        protected override void OnAbort()
        {
            IChannel[] currentChannels = _channels.ToArray();
            foreach (IChannel channel in currentChannels)
                channel.Abort();
 
            _channels.Abort();
        }
 
        protected override void OnClose(TimeSpan timeout)
        {
            IChannel[] currentChannels = _channels.ToArray();
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            foreach (IChannel channel in currentChannels)
                channel.Close(timeoutHelper.RemainingTime());
 
            _channels.Close(timeoutHelper.RemainingTime());
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new ChainedCloseAsyncResult(timeout, callback, state,
                _channels.BeginClose, _channels.EndClose,
                _channels.ToArray());
        }
 
        protected override void OnEndClose(IAsyncResult result)
        {
            ChainedCloseAsyncResult.End(result);
        }
    }
}