ClientFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Routing / System / ServiceModel / Routing / ClientFactory.cs / 1305376 / ClientFactory.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------

namespace System.ServiceModel.Routing 
{
    using System; 
    using System.Collections.Generic; 
    using System.Runtime;
    using System.ServiceModel; 
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;
    using System.Transactions;
 
    static class ClientFactory
    { 
        public static IRoutingClient Create(RoutingEndpointTrait endpointTrait, RoutingService service, bool impersonating) 
        {
            Type contractType = endpointTrait.RouterContract; 
            IRoutingClient client;
            if (contractType == typeof(ISimplexDatagramRouter))
            {
                client = new SimplexDatagramClient(endpointTrait, service.RoutingConfig, impersonating); 
            }
            else if (contractType == typeof(IRequestReplyRouter)) 
            { 
                client = new RequestReplyClient(endpointTrait, service.RoutingConfig, impersonating);
            } 
            else if (contractType == typeof(ISimplexSessionRouter))
            {
                client = new SimplexSessionClient(endpointTrait, service.RoutingConfig, impersonating);
            } 
            else //if (contractType == typeof(IDuplexSessionRouter))
            { 
                Fx.Assert(contractType == typeof(IDuplexSessionRouter), "Only one contract type remaining."); 
                client = new DuplexSessionClient(service, endpointTrait, impersonating);
            } 

            return client;
        }
 
        abstract class RoutingClientBase : ClientBase, IRoutingClient
            where TChannel : class 
        { 
            bool openCompleted;
            object thisLock; 
            Queue waiters;

            protected RoutingClientBase(RoutingEndpointTrait endpointTrait, RoutingConfiguration routingConfig, bool impersonating)
                : base(endpointTrait.Endpoint.Binding, endpointTrait.Endpoint.Address) 
            {
                Initialize(endpointTrait, routingConfig, impersonating); 
            } 

            protected RoutingClientBase(RoutingEndpointTrait endpointTrait, RoutingConfiguration routingConfig, object callbackInstance, bool impersonating) 
                : base(new InstanceContext(callbackInstance), endpointTrait.Endpoint.Binding, endpointTrait.Endpoint.Address)
            {
                Initialize(endpointTrait, routingConfig, impersonating);
            } 

            public RoutingEndpointTrait Key 
            { 
                get;
                private set; 
            }

            public event EventHandler Faulted;
 
            static void ConfigureImpersonation(ServiceEndpoint endpoint, bool impersonating)
            { 
                // Used for both impersonation and ASP.NET Compatibilty Mode.  Both currently require 
                // everything to be synchronous.
                if (impersonating) 
                {
                    CustomBinding binding = endpoint.Binding as CustomBinding;
                    if (binding == null)
                    { 
                        binding = new CustomBinding(endpoint.Binding);
                    } 
 
                    SynchronousSendBindingElement syncSend = binding.Elements.Find();
                    if (syncSend == null) 
                    {
                        binding.Elements.Insert(0, new SynchronousSendBindingElement());
                        endpoint.Binding = binding;
                    } 
                }
            } 
 
            static void ConfigureTransactionFlow(ServiceEndpoint endpoint)
            { 
                CustomBinding binding = endpoint.Binding as CustomBinding;
                if (binding == null)
                {
                    binding = new CustomBinding(endpoint.Binding); 
                }
                TransactionFlowBindingElement transactionFlow = binding.Elements.Find(); 
                if (transactionFlow != null) 
                {
                    transactionFlow.AllowWildcardAction = true; 
                    endpoint.Binding = binding;
                }
            }
 
            void Initialize(RoutingEndpointTrait endpointTrait, RoutingConfiguration routingConfig, bool impersonating)
            { 
                this.thisLock = new object(); 
                this.Key = endpointTrait;
                if (TD.RoutingServiceCreatingClientForEndpointIsEnabled()) 
                {
                    TD.RoutingServiceCreatingClientForEndpoint(this.Key.ToString());
                }
                ServiceEndpoint clientEndpoint = endpointTrait.Endpoint; 
                ServiceEndpoint endpoint = this.Endpoint;
                KeyedByTypeCollection behaviors = endpoint.Behaviors; 
                endpoint.ListenUri = clientEndpoint.ListenUri; 
                endpoint.ListenUriMode = clientEndpoint.ListenUriMode;
                endpoint.Name = clientEndpoint.Name; 
                foreach (IEndpointBehavior behavior in clientEndpoint.Behaviors)
                {
                    // Remove if present, ok to call if not there (will simply return false)
                    behaviors.Remove(behavior.GetType()); 
                    behaviors.Add(behavior);
                } 
 
                // If the configuration doesn't explicitly add MustUnderstandBehavior (to override us)
                // add it here, with mustunderstand = false. 
                if (behaviors.Find() == null)
                {
                    behaviors.Add(new MustUnderstandBehavior(false));
                } 

                // If the configuration doesn't explicitly turn off marshaling we add it here. 
                if (routingConfig.SoapProcessingEnabled && behaviors.Find() == null) 
                {
                    behaviors.Add(new SoapProcessingBehavior()); 
                }

                ConfigureTransactionFlow(endpoint);
                ConfigureImpersonation(endpoint, impersonating); 
            }
 
            protected override TChannel CreateChannel() 
            {
                TChannel channel = base.CreateChannel(); 
                ((ICommunicationObject)channel).Faulted += this.InnerChannelFaulted;
                return channel;
            }
 
            public IAsyncResult BeginOperation(Message message, Transaction transaction, AsyncCallback callback, object state)
            { 
                return new OperationAsyncResult(this, message, transaction, callback, state); 
            }
 
            public Message EndOperation(IAsyncResult result)
            {
                return OperationAsyncResult.End(result);
            } 

            protected abstract IAsyncResult OnBeginOperation(Message message, AsyncCallback callback, object state); 
            protected abstract Message OnEndOperation(IAsyncResult asyncResult); 

            void InnerChannelFaulted(object sender, EventArgs args) 
            {
                EventHandler handlers = this.Faulted;
                if (handlers != null)
                { 
                    handlers(this, args);
                } 
            } 

            class OperationAsyncResult : AsyncResult 
            {
                static AsyncCompletion openComplete = OpenComplete;
                static AsyncCompletion operationComplete = OperationComplete;
                static Action signalWaiter; 

                RoutingClientBase parent; 
                Message replyMessage; 
                Message requestMessage;
                Transaction transaction; 

                public OperationAsyncResult(RoutingClientBase parent, Message requestMessage, Transaction transaction, AsyncCallback callback, object state)
                    : base(callback, state)
                { 
                    this.parent = parent;
                    this.requestMessage = requestMessage; 
                    this.transaction = transaction; 

                    bool shouldOpen = false; 

                    if (!this.parent.openCompleted)
                    {
                        lock (this.parent.thisLock) 
                        {
                            if (!this.parent.openCompleted) 
                            { 
                                //The first to open initializes the waiters queue others add themselves to it.
                                if (this.parent.waiters == null) 
                                {
                                    //it's our job to open the proxy
                                    this.parent.waiters = new Queue();
                                    shouldOpen = true; 
                                }
                                else 
                                { 
                                    //Someone beat us to it, just join the list of waiters.
                                    this.parent.waiters.Enqueue(this); 
                                    return;
                                }
                            }
                        } 
                    }
 
                    if (shouldOpen) 
                    {
                        //we are the first so we need to open this channel 
                        IAsyncResult asyncResult;
                        using (this.PrepareTransactionalCall(this.transaction))
                        {
                            //This will use the binding's OpenTimeout. 
                            asyncResult = ((ICommunicationObject)this.parent).BeginOpen(this.PrepareAsyncCompletion(openComplete), this);
                        } 
                        if (this.SyncContinue(asyncResult)) 
                        {
                            this.Complete(true); 
                        }
                    }
                    else
                    { 
                        if (this.CallOperation())
                        { 
                            this.Complete(true); 
                        }
                    } 
                }

                public static Message End(IAsyncResult result)
                { 
                    OperationAsyncResult thisPtr = AsyncResult.End(result);
                    return thisPtr.replyMessage; 
                } 

                static bool OpenComplete(IAsyncResult openResult) 
                {
                    OperationAsyncResult thisPtr = (OperationAsyncResult)openResult.AsyncState;
                    try
                    { 
                        ((ICommunicationObject)thisPtr.parent).EndOpen(openResult);
                    } 
                    finally 
                    {
                        Queue localWaiters = null; 

                        lock (thisPtr.parent.thisLock)
                        {
                            localWaiters = thisPtr.parent.waiters; 
                            thisPtr.parent.waiters = null;
                            thisPtr.parent.openCompleted = true; 
                        } 

                        if (localWaiters != null && localWaiters.Count > 0) 
                        {
                            if (signalWaiter == null)
                            {
                                signalWaiter = new Action(SignalWaiter); 
                            }
 
                            //foreach over Queue goes FIFO 
                            foreach (OperationAsyncResult waiter in localWaiters)
                            { 
                                ActionItem.Schedule(signalWaiter, waiter);
                            }
                        }
                    } 
                    return thisPtr.CallOperation();
                } 
 
                bool CallOperation()
                { 
                    IAsyncResult asyncResult;
                    using (this.PrepareTransactionalCall(this.transaction))
                    {
                        asyncResult = this.parent.OnBeginOperation(this.requestMessage, this.PrepareAsyncCompletion(operationComplete), this); 
                    }
                    return this.SyncContinue(asyncResult); 
                } 

                static bool OperationComplete(IAsyncResult result) 
                {
                    OperationAsyncResult thisPtr = (OperationAsyncResult)result.AsyncState;
                    thisPtr.replyMessage = thisPtr.parent.OnEndOperation(result);
                    return true; 
                }
 
                static void SignalWaiter(object state) 
                {
                    OperationAsyncResult waiter = (OperationAsyncResult)state; 
                    try
                    {
                        if (waiter.CallOperation())
                        { 
                            waiter.Complete(false);
                        } 
                    } 
                    catch (Exception exception)
                    { 
                        if (Fx.IsFatal(exception))
                        {
                            throw;
                        } 
                        waiter.Complete(false, exception);
                    } 
                } 
            }
        } 

        class SimplexDatagramClient : RoutingClientBase
        {
            public SimplexDatagramClient(RoutingEndpointTrait endpointTrait, RoutingConfiguration routingConfig, bool impersonating) 
                : base(endpointTrait, routingConfig, impersonating)
            { 
            } 

            protected override IAsyncResult OnBeginOperation(Message message, AsyncCallback callback, object state) 
            {
                return this.Channel.BeginProcessMessage(message, callback, state);
            }
 
            protected override Message OnEndOperation(IAsyncResult result)
            { 
                this.Channel.EndProcessMessage(result); 
                return null;
            } 
        }

        class SimplexSessionClient : RoutingClientBase
        { 
            public SimplexSessionClient(RoutingEndpointTrait endointTrait, RoutingConfiguration routingConfig, bool impersonating)
                : base(endointTrait, routingConfig, impersonating) 
            { 
            }
 
            protected override IAsyncResult OnBeginOperation(Message message, AsyncCallback callback, object state)
            {
                return this.Channel.BeginProcessMessage(message, callback, state);
            } 

            protected override Message OnEndOperation(IAsyncResult result) 
            { 
                this.Channel.EndProcessMessage(result);
                return null; 
            }
        }

        class DuplexSessionClient : RoutingClientBase 
        {
            public DuplexSessionClient(RoutingService service, RoutingEndpointTrait endpointTrait, bool impersonating) 
                : base(endpointTrait, service.RoutingConfig, new DuplexCallbackProxy(service.ChannelExtension.ActivityID, endpointTrait.CallbackInstance), impersonating) 
            {
            } 

            protected override IAsyncResult OnBeginOperation(Message message, AsyncCallback callback, object state)
            {
                return this.Channel.BeginProcessMessage(message, callback, state); 
            }
 
            protected override Message OnEndOperation(IAsyncResult result) 
            {
                this.Channel.EndProcessMessage(result); 
                return null;
            }

            class DuplexCallbackProxy : IDuplexRouterCallback 
            {
                Guid activityID; 
                IDuplexRouterCallback callbackInstance; 

                public DuplexCallbackProxy(Guid activityID, IDuplexRouterCallback callbackInstance) 
                {
                    this.activityID = activityID;
                    this.callbackInstance = callbackInstance;
                } 

                IAsyncResult IDuplexRouterCallback.BeginProcessMessage(Message message, AsyncCallback callback, object state) 
                { 
                    FxTrace.Trace.SetAndTraceTransfer(this.activityID, true);
                    try 
                    {
                        return new CallbackAsyncResult(this.callbackInstance, message, callback, state);
                    }
                    catch (Exception e) 
                    {
                        if (TD.RoutingServiceDuplexCallbackExceptionIsEnabled()) 
                        { 
                            TD.RoutingServiceDuplexCallbackException("DuplexCallbackProxy.BeginProcessMessage", e);
                        } 
                        throw;
                    }
                }
 
                void IDuplexRouterCallback.EndProcessMessage(IAsyncResult result)
                { 
                    FxTrace.Trace.SetAndTraceTransfer(this.activityID, true); 
                    try
                    { 
                        CallbackAsyncResult.End(result);
                    }
                    catch (Exception e)
                    { 
                        if (TD.RoutingServiceDuplexCallbackExceptionIsEnabled())
                        { 
                            TD.RoutingServiceDuplexCallbackException("DuplexCallbackProxy.EndProcessMessage", e); 
                        }
                        throw; 
                    }
                }

                // We have to have an AsyncResult implementation here in order to handle the 
                // TransactionScope appropriately (use PrepareTransactionalCall, SyncContinue, etc...)
                class CallbackAsyncResult : AsyncResult 
                { 
                    static AsyncCompletion processCallback = ProcessCallback;
                    IDuplexRouterCallback callbackInstance; 

                    public CallbackAsyncResult(IDuplexRouterCallback callbackInstance, Message message, AsyncCallback callback, object state)
                        : base(callback, state)
                    { 
                        this.callbackInstance = callbackInstance;
 
                        IAsyncResult result; 
                        using (this.PrepareTransactionalCall(TransactionMessageProperty.TryGetTransaction(message)))
                        { 
                            result = this.callbackInstance.BeginProcessMessage(message,
                                this.PrepareAsyncCompletion(processCallback), this);
                        }
 
                        if (this.SyncContinue(result))
                        { 
                            this.Complete(true); 
                        }
                    } 

                    public static void End(IAsyncResult result)
                    {
                        AsyncResult.End(result); 
                    }
 
                    static bool ProcessCallback(IAsyncResult result) 
                    {
                        CallbackAsyncResult thisPtr = (CallbackAsyncResult)result.AsyncState; 
                        thisPtr.callbackInstance.EndProcessMessage(result);
                        return true;
                    }
                } 
            }
        } 
 
        class RequestReplyClient : RoutingClientBase
        { 
            public RequestReplyClient(RoutingEndpointTrait endpointTrait, RoutingConfiguration routingConfig, bool impersonating)
                : base(endpointTrait, routingConfig, impersonating)
            {
            } 

            protected override IAsyncResult OnBeginOperation(Message message, AsyncCallback callback, object state) 
            { 
                return this.Channel.BeginProcessRequest(message, callback, state);
            } 

            protected override Message OnEndOperation(IAsyncResult result)
            {
                return this.Channel.EndProcessRequest(result); 
            }
        } 
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK