File: System\ServiceModel\Routing\SessionChannels.cs
Project: ndp\cdf\src\NetFx40\System.ServiceModel.Routing\System.ServiceModel.Routing.csproj (System.ServiceModel.Routing)
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//----------------------------------------------------------------
 
namespace System.ServiceModel.Routing
{
    using System;
    using System.Diagnostics.CodeAnalysis;
    using System.Collections.Generic;
    using System.Runtime;
    using System.ServiceModel.Description;
    using System.ServiceModel.Channels;
    using System.ComponentModel;
    using System.Threading;
 
    class SessionChannels
    {
        Guid activityID;
        [Fx.Tag.SynchronizationObject]
        Dictionary<RoutingEndpointTrait, IRoutingClient> sessions;
        List<IRoutingClient> sessionList;
 
        [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "gets called in RoutingService.ctor()")]
        public SessionChannels(Guid activityID)
        {
            this.activityID = activityID;
            this.sessions = new Dictionary<RoutingEndpointTrait, IRoutingClient>();
            this.sessionList = new List<IRoutingClient>();
        }
 
        void ChannelFaulted(object sender, EventArgs args)
        {
            FxTrace.Trace.SetAndTraceTransfer(this.activityID, true);
            IRoutingClient client = (IRoutingClient)sender;
            if (TD.RoutingServiceChannelFaultedIsEnabled())
            {
                TD.RoutingServiceChannelFaulted(client.Key.ToString());
            }
            this.AbortChannel(client.Key);
        }
 
        [SuppressMessage(FxCop.Category.Performance, FxCop.Rule.AvoidUncalledPrivateCode, Justification = "BeginClose is called by RoutingChannelExtension.AttachService")]
        public IAsyncResult BeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            List<ICommunicationObject> localClients = null;
 
            lock (this.sessions)
            {
                if (this.sessions.Count > 0)
                {
                    localClients = this.sessionList.ConvertAll<ICommunicationObject>((client) => (ICommunicationObject)client);
                    this.sessionList.Clear();
                    this.sessions.Clear();
                }
            }
 
            if (localClients != null && localClients.Count > 0)
            {
                localClients.ForEach((client) =>
                {
                    if (TD.RoutingServiceClosingClientIsEnabled())
                    {
                        TD.RoutingServiceClosingClient(((IRoutingClient)client).Key.ToString());
                    }
                });
                return new CloseCollectionAsyncResult(timeout, callback, state, localClients);
            }
            else
            {
                return new CompletedAsyncResult(callback, state);
            }
        }
 
        public void EndClose(IAsyncResult asyncResult)
        {
            if (asyncResult is CloseCollectionAsyncResult)
            {
                CloseCollectionAsyncResult.End(asyncResult);
            }
            else
            {
                CompletedAsyncResult.End(asyncResult);
            }
        }
 
        internal IRoutingClient GetOrCreateClient<TContract>(RoutingEndpointTrait key, RoutingService service, bool impersonating)
        {
            IRoutingClient value;
            lock (this.sessions)
            {
                if (!this.sessions.TryGetValue(key, out value))
                {
                    //Create the client here
                    value = ClientFactory.Create(key, service, impersonating);
                    value.Faulted += ChannelFaulted;
                    this.sessions[key] = value;
                    sessionList.Add(value);
                }
            }
            return value;
        }
 
        public void AbortAll()
        {
            List<IRoutingClient> clients = new List<IRoutingClient>();
 
            lock (this.sessions)
            {
                foreach (IRoutingClient client in this.sessions.Values)
                {
                    clients.Add(client);
                }
                this.sessions.Clear();
                this.sessionList.Clear();
            }
 
            foreach (IRoutingClient client in clients)
            {
                RoutingUtilities.Abort((ICommunicationObject)client, client.Key);
            }
        }
 
        public void AbortChannel(RoutingEndpointTrait key)
        {
            IRoutingClient client;
            lock (this.sessions)
            {
                if (this.sessions.TryGetValue(key, out client))
                {
                    this.sessions.Remove(key);
                    this.sessionList.Remove(client);
                }
            }
 
            if (client != null)
            {
                RoutingUtilities.Abort((ICommunicationObject)client, client.Key);
            }
        }
 
        public IRoutingClient ReleaseChannel()
        {
            IRoutingClient client = null;
            lock (this.sessions)
            {
                int count = this.sessionList.Count;
                if (count > 0)
                {
                    client = this.sessionList[count - 1];
                    this.sessionList.RemoveAt(count - 1);
                    this.sessions.Remove(client.Key);
                }
            }
            return client;
        }
    }
}