File: System\ServiceModel\Discovery\DiscoveryClientChannelFactory.cs
Project: ndp\cdf\src\NetFx40\System.ServiceModel.Discovery\System.ServiceModel.Discovery.csproj (System.ServiceModel.Discovery)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
 
namespace System.ServiceModel.Discovery
{
    using System;
    using System.Runtime;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
 
    class DiscoveryClientChannelFactory<TChannel> : ChannelFactoryBase<TChannel>
    {
        DiscoveryEndpointProvider discoveryEndpointProvider;
        FindCriteria findCriteria;
 
        IChannelFactory<TChannel> innerChannelFactory;
 
        public DiscoveryClientChannelFactory(IChannelFactory<TChannel> innerChannelFactory, FindCriteria findCriteria, DiscoveryEndpointProvider discoveryEndpointProvider)
        {
            Fx.Assert(findCriteria != null, "The findCriteria must be non null.");
            Fx.Assert(discoveryEndpointProvider != null, "The discoveryEndpointProvider must be non null.");
            Fx.Assert(innerChannelFactory != null, "The innerChannelFactory must be non null.");
 
            this.findCriteria = findCriteria;
            this.discoveryEndpointProvider = discoveryEndpointProvider;
            this.innerChannelFactory = innerChannelFactory;            
        }        
 
        protected override TChannel OnCreateChannel(EndpointAddress address, Uri via)
        {
            if (!address.Equals(DiscoveryClientBindingElement.DiscoveryEndpointAddress))
            {
                throw FxTrace.Exception.Argument(
                    "address",
                    Discovery.SR.DiscoveryEndpointAddressIncorrect("address", address.Uri, DiscoveryClientBindingElement.DiscoveryEndpointAddress.Uri));
            }
 
            if (!via.Equals(DiscoveryClientBindingElement.DiscoveryEndpointAddress.Uri))
            {
                throw FxTrace.Exception.Argument(
                    "via",
                    Discovery.SR.DiscoveryEndpointAddressIncorrect("via", via, DiscoveryClientBindingElement.DiscoveryEndpointAddress.Uri));
            }
 
            if (typeof(TChannel) == typeof(IOutputChannel))
            {
                return (TChannel)(object)new DiscoveryClientOutputChannel<IOutputChannel>(
                    this,
                    (IChannelFactory<IOutputChannel>)this.innerChannelFactory, 
                    this.findCriteria,
                    this.discoveryEndpointProvider);
            }
            else if (typeof(TChannel) == typeof(IRequestChannel))
            {
                return (TChannel)(object)new DiscoveryClientRequestChannel<IRequestChannel>(
                    this,
                    (IChannelFactory<IRequestChannel>)this.innerChannelFactory,
                    this.findCriteria,
                    this.discoveryEndpointProvider);
            }
            else if (typeof(TChannel) == typeof(IDuplexChannel))            
            {
                return (TChannel)(object)new DiscoveryClientDuplexChannel<IDuplexChannel>(
                    this,
                    (IChannelFactory<IDuplexChannel>)this.innerChannelFactory,
                    this.findCriteria,
                    this.discoveryEndpointProvider);
            }
            else if (typeof(TChannel) == typeof(IOutputSessionChannel))
            {
                return (TChannel)(object)new DiscoveryClientOutputSessionChannel(
                    this,
                    (IChannelFactory<IOutputSessionChannel>)this.innerChannelFactory,
                    this.findCriteria,
                    this.discoveryEndpointProvider);
            }
            else if (typeof(TChannel) == typeof(IRequestSessionChannel))
            {
                return (TChannel)(object)new DiscoveryClientRequestSessionChannel(
                    this,
                    (IChannelFactory<IRequestSessionChannel>)this.innerChannelFactory,
                    this.findCriteria,
                    this.discoveryEndpointProvider);
            }
            else if (typeof(TChannel) == typeof(IDuplexSessionChannel))
            {
                return (TChannel)(object)new DiscoveryClientDuplexSessionChannel(
                    this,
                    (IChannelFactory<IDuplexSessionChannel>)this.innerChannelFactory,
                    this.findCriteria,
                    this.discoveryEndpointProvider);
            }
 
            throw FxTrace.Exception.Argument("TChannel", ServiceModel.SR.GetString(ServiceModel.SR.ChannelTypeNotSupported, typeof(TChannel)));
        }
 
        public override T GetProperty<T>()
        {
            if (typeof(T) == typeof(IChannelFactory<TChannel>))
            {
                return (T)(object)this;
            }
 
            T baseProperty = base.GetProperty<T>();
            if (baseProperty != null)
            {
                return baseProperty;
            }
 
            return this.innerChannelFactory.GetProperty<T>();
        }
 
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return this.innerChannelFactory.BeginOpen(timeout, callback, state);
        }
 
        protected override void OnEndOpen(IAsyncResult result)
        {
            this.innerChannelFactory.EndOpen(result);
        }
 
        protected override void OnOpen(TimeSpan timeout)
        {
            this.innerChannelFactory.Open(timeout);
        }
 
        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            // Must close higher channels before closing lower channels.
            return new ChainedAsyncResult(
                timeout, 
                callback, 
                state, 
                base.OnBeginClose, 
                base.OnEndClose, 
                this.innerChannelFactory.BeginClose,
                this.innerChannelFactory.EndClose);
        }
 
        protected override void OnEndClose(IAsyncResult result)
        {
            ChainedAsyncResult.End(result);
        }
 
        protected override void OnClose(TimeSpan timeout)
        {
            // Must close higher channels before closing lower channels.
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            base.OnClose(timeoutHelper.RemainingTime());
            this.innerChannelFactory.Close(timeoutHelper.RemainingTime());
        }
 
        protected override void OnAbort()
        {
            // Must abort higher channels before aborting lower channels.
            base.OnAbort();            
            this.innerChannelFactory.Abort();
        }
    }
}