WorkflowServiceHost.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.Activities / System / ServiceModel / Activities / WorkflowServiceHost.cs / 1599917 / WorkflowServiceHost.cs

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

namespace System.ServiceModel.Activities 
{
    using System.Activities; 
    using System.Activities.Hosting; 
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.Diagnostics.CodeAnalysis;
    using System.Runtime;
    using System.Runtime.DurableInstancing;
    using System.ServiceModel.Activities.Description; 
    using System.ServiceModel.Activities.Dispatcher;
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Description; 
    using System.Xml.Linq;
 
    [Fx.Tag.XamlVisible(false)]
    public class WorkflowServiceHost : ServiceHostBase
    {
        static readonly XName mexContractXName = XName.Get(ServiceMetadataBehavior.MexContractName, ServiceMetadataBehavior.MexContractNamespace); 
        static readonly Type mexBehaviorType = typeof(ServiceMetadataBehavior);
        static readonly TimeSpan defaultPersistTimeout = TimeSpan.FromSeconds(30); 
        static readonly TimeSpan defaultTrackTimeout = TimeSpan.FromSeconds(30); 
        static readonly TimeSpan defaultFilterResumeTimeout = TimeSpan.FromMinutes(1);
        static readonly Type baseActivityType = typeof(Activity); 
        static readonly Type correlationQueryBehaviorType = typeof(CorrelationQueryBehavior);
        static readonly Type bufferedReceiveServiceBehaviorType = typeof(BufferedReceiveServiceBehavior);

        WorkflowServiceHostExtensions workflowExtensions; 
        DurableInstanceManager durableInstanceManager;
 
        Activity activity; 
        WorkflowService serviceDefinition;
        IDictionary inferredContracts; 
        IDictionary> correlationQueries;

        WorkflowUnhandledExceptionAction unhandledExceptionAction;
        TimeSpan idleTimeToPersist; 
        TimeSpan idleTimeToUnload;
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotCallOverridableMethodsInConstructors, 
            Justification = "Based on prior are from WCF3: By design, don't want to complicate ServiceHost state model")]
        public WorkflowServiceHost(object serviceImplementation, params Uri[] baseAddresses) 
            : base()
        {
            if (serviceImplementation == null)
            { 
                throw FxTrace.Exception.ArgumentNull("serviceImplementation");
            } 
 
            if (serviceImplementation is WorkflowService)
            { 
                InitializeFromConstructor((WorkflowService)serviceImplementation, baseAddresses);
            }
            else
            { 
                Activity activity = serviceImplementation as Activity;
                if (activity == null) 
                { 
                    throw FxTrace.Exception.Argument("serviceImplementation", SR.InvalidServiceImplementation);
                } 
                InitializeFromConstructor(activity, baseAddresses);
            }
        }
 

        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotCallOverridableMethodsInConstructors, 
            Justification = "Based on prior are from WCF3: By design, don't want to complicate ServiceHost state model")] 
        public WorkflowServiceHost(Activity activity, params Uri[] baseAddresses)
            : base() 
        {
            if (activity == null)
            {
                throw FxTrace.Exception.ArgumentNull("activity"); 
            }
 
            InitializeFromConstructor(activity, baseAddresses); 
        }
 
        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotCallOverridableMethodsInConstructors,
            Justification = "Based on prior art from WCF 3.0: By design, don't want to complicate ServiceHost state model")]
        public WorkflowServiceHost(WorkflowService serviceDefinition, params Uri[] baseAddresses)
            : base() 
        {
            if (serviceDefinition == null) 
            { 
                throw FxTrace.Exception.ArgumentNull("serviceDefinition");
            } 

            InitializeFromConstructor(serviceDefinition, baseAddresses);

        } 

        [SuppressMessage(FxCop.Category.Usage, FxCop.Rule.DoNotCallOverridableMethodsInConstructors, 
            Justification = "Based on prior art from WCF 3.0: By design, don't want to complicate ServiceHost state model")] 
        protected WorkflowServiceHost()
        { 
            InitializeFromConstructor((WorkflowService)null);
        }

        public Activity Activity 
        {
            get 
            { 
                return this.activity;
            } 
        }

        public WorkflowInstanceExtensionManager WorkflowExtensions
        { 
            get
            { 
                return this.workflowExtensions; 
            }
        } 

        public DurableInstancingOptions DurableInstancingOptions
        {
            get 
            {
                return this.durableInstanceManager.DurableInstancingOptions; 
            } 
        }
 
        internal XName ServiceName
        {
            get;
            set; 
        }
 
        internal TimeSpan PersistTimeout 
        {
            get; 
            set;
        }

        internal TimeSpan TrackTimeout 
        {
            get; 
            set; 
        }
 
        //
        internal TimeSpan FilterResumeTimeout
        {
            get; 
            set;
        } 
 
        internal DurableInstanceManager DurableInstanceManager
        { 
            get
            {
                return this.durableInstanceManager;
            } 
        }
 
        internal bool IsLoadTransactionRequired 
        {
            get; 
            private set;
        }

        // set by WorkflowUnhandledExceptionBehavior.ApplyDispatchBehavior, used by WorkflowServiceInstance.UnhandledExceptionPolicy 
        internal WorkflowUnhandledExceptionAction UnhandledExceptionAction
        { 
            get { return this.unhandledExceptionAction; } 
            set
            { 
                Fx.Assert(WorkflowUnhandledExceptionActionHelper.IsDefined(value), "Undefined WorkflowUnhandledExceptionAction");
                this.unhandledExceptionAction = value;
            }
        } 

        // set by WorkflowIdleBehavior.ApplyDispatchBehavior, used by WorkflowServiceInstance.UnloadInstancePolicy 
        internal TimeSpan IdleTimeToPersist 
        {
            get { return this.idleTimeToPersist; } 
            set
            {
                Fx.Assert(value >= TimeSpan.Zero, "IdleTimeToPersist cannot be less than zero");
                this.idleTimeToPersist = value; 
            }
        } 
        internal TimeSpan IdleTimeToUnload 
        {
            get { return this.idleTimeToUnload; } 
            set
            {
                Fx.Assert(value >= TimeSpan.Zero, "IdleTimeToUnload cannot be less than zero");
                this.idleTimeToUnload = value; 
            }
        } 
 
        void InitializeFromConstructor(Activity activity, params Uri[] baseAddresses)
        { 
            WorkflowService serviceDefinition = new WorkflowService
            {
                Body = activity
            }; 

            InitializeFromConstructor(serviceDefinition, baseAddresses); 
        } 

        void InitializeFromConstructor(WorkflowService serviceDefinition, params Uri[] baseAddresses) 
        {
            // first initialize some values to their defaults
            this.idleTimeToPersist = WorkflowIdleBehavior.defaultTimeToPersist;
            this.idleTimeToUnload = WorkflowIdleBehavior.defaultTimeToUnload; 
            this.unhandledExceptionAction = WorkflowUnhandledExceptionBehavior.defaultAction;
            this.workflowExtensions = new WorkflowServiceHostExtensions(); 
 
            if(TD.CreateWorkflowServiceHostStartIsEnabled())
            { 
                TD.CreateWorkflowServiceHostStart();
            }
            if (serviceDefinition != null)
            { 
                InitializeDescription(serviceDefinition, new UriSchemeKeyedCollection(baseAddresses));
            } 
            this.durableInstanceManager = new DurableInstanceManager(this); 
            if (TD.CreateWorkflowServiceHostStopIsEnabled())
            { 
                TD.CreateWorkflowServiceHostStop();
            }
        }
 
        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DefaultParametersShouldNotBeUsed, Justification = "Temporary suppression - to be addressed by DCR 127467")]
        public ServiceEndpoint AddServiceEndpoint(XName serviceContractName, Binding binding, string address, 
            Uri listenUri = null, string behaviorConfigurationName = null) 
        {
            return AddServiceEndpoint(serviceContractName, binding, new Uri(address, UriKind.RelativeOrAbsolute), listenUri, behaviorConfigurationName); 
        }

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DefaultParametersShouldNotBeUsed, Justification = "Temporary suppression - to be addressed by DCR 127467")]
        public ServiceEndpoint AddServiceEndpoint(XName serviceContractName, Binding binding, Uri address, 
            Uri listenUri = null, string behaviorConfigurationName = null)
        { 
            if (binding == null) 
            {
                throw FxTrace.Exception.ArgumentNull("binding"); 
            }
            if (address == null)
            {
                throw FxTrace.Exception.ArgumentNull("address"); 
            }
 
            Uri via = this.MakeAbsoluteUri(address, binding); 
            return AddServiceEndpointCore(serviceContractName, binding, new EndpointAddress(via), listenUri, behaviorConfigurationName);
        } 

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.DefaultParametersShouldNotBeUsed, Justification = "Temporary suppression - to be addressed by DCR 127467")]
        ServiceEndpoint AddServiceEndpointCore(XName serviceContractName, Binding binding, EndpointAddress address,
            Uri listenUri = null, string behaviorConfigurationName = null) 
        {
            if (serviceContractName == null) 
            { 
                throw FxTrace.Exception.ArgumentNull("serviceContractName");
            } 
            if (this.inferredContracts == null)
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException(
                    SR.ContractNotFoundInAddServiceEndpoint(serviceContractName.LocalName, serviceContractName.NamespaceName))); 
            }
 
            ServiceEndpoint serviceEndpoint; 
            ContractDescription description;
 
            ContractInferenceHelper.ProvideDefaultNamespace(ref serviceContractName);

            if (this.inferredContracts.TryGetValue(serviceContractName, out description))
            { 
                serviceEndpoint = new ServiceEndpoint(description, binding, address);
 
                if (!string.IsNullOrEmpty(behaviorConfigurationName)) 
                {
                    ConfigLoader.LoadChannelBehaviors(behaviorConfigurationName, null, serviceEndpoint.Behaviors); 
                }
            }
            else if (serviceContractName == mexContractXName)  // Special case for mex endpoint
            { 
                if (!this.Description.Behaviors.Contains(mexBehaviorType))
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException( 
                        SR.ServiceMetadataBehaviorNotFoundForServiceMetadataEndpoint(this.Description.Name)));
                } 

                serviceEndpoint = new ServiceMetadataEndpoint(binding, address);
            }
            else 
            {
                throw FxTrace.Exception.AsError(new InvalidOperationException( 
                    SR.ContractNotFoundInAddServiceEndpoint(serviceContractName.LocalName, serviceContractName.NamespaceName))); 
            }
 
            if (listenUri != null)
            {
                listenUri = base.MakeAbsoluteUri(listenUri, binding);
                serviceEndpoint.ListenUri = listenUri; 
            }
 
            base.Description.Endpoints.Add(serviceEndpoint); 

            if (TD.ServiceEndpointAddedIsEnabled()) 
            {
                TD.ServiceEndpointAdded(address.Uri.ToString(), binding.GetType().ToString(), serviceEndpoint.Contract.Name);
            }
 
            return serviceEndpoint;
        } 
 
        // Duplicate public AddServiceEndpoint methods from the base class
        // This is to ensure that base class methods with string are not hidden by derived class methods with XName 
        public new ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address)
        {
            return base.AddServiceEndpoint(implementedContract, binding, address);
        } 

        public new ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address) 
        { 
            return base.AddServiceEndpoint(implementedContract, binding, address);
        } 

        public new ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri)
        {
            return base.AddServiceEndpoint(implementedContract, binding, address, listenUri); 
        }
 
        public new ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri) 
        {
            return base.AddServiceEndpoint(implementedContract, binding, address, listenUri); 
        }

        public override void AddServiceEndpoint(ServiceEndpoint endpoint)
        { 
            if (!endpoint.IsSystemEndpoint)
            { 
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.CannotUseAddServiceEndpointOverloadForWorkflowServices)); 
            }
 
            base.AddServiceEndpoint(endpoint);
        }

        internal override void AddDefaultEndpoints(Binding defaultBinding, List defaultEndpoints) 
        {
            if (this.inferredContracts != null) 
            { 
                foreach (XName contractName in this.inferredContracts.Keys)
                { 
                    ServiceEndpoint endpoint = AddServiceEndpoint(contractName, defaultBinding, String.Empty);
                    ConfigLoader.LoadDefaultEndpointBehaviors(endpoint);
                    AddCorrelationQueryBehaviorToServiceEndpoint(endpoint);
                    defaultEndpoints.Add(endpoint); 
                }
            } 
        } 

        [SuppressMessage(FxCop.Category.Design, FxCop.Rule.AvoidOutParameters, MessageId = "0#", Justification = "This is defined by the ServiceHost base class")] 
        protected override ServiceDescription CreateDescription(out IDictionary implementedContracts)
        {
            Fx.AssertAndThrow(this.serviceDefinition != null, "serviceDefinition is null");
 
            this.activity = this.serviceDefinition.Body;
 
            Dictionary result = new Dictionary(); 

            // Note: We do not check whether this.inferredContracts == null || this.inferredContracts.Count == 0, 
            // because we need to support hosting workflow with zero contract.
            this.inferredContracts = this.serviceDefinition.GetContractDescriptions();

            if (this.inferredContracts != null) 
            {
                foreach (ContractDescription contract in this.inferredContracts.Values) 
                { 
                    if (!string.IsNullOrEmpty(contract.ConfigurationName))
                    { 
                        if (result.ContainsKey(contract.ConfigurationName))
                        {
                            throw FxTrace.Exception.AsError(new InvalidOperationException(SR.DifferentContractsSameConfigName));
                        } 
                        result.Add(contract.ConfigurationName, contract);
                    } 
                } 
            }
            implementedContracts = result; 

            // Currently, only WorkflowService has CorrelationQueries property
            this.correlationQueries = this.serviceDefinition.CorrelationQueries;
 
            return this.serviceDefinition.GetEmptyServiceDescription();
        } 
 
        void InitializeDescription(WorkflowService serviceDefinition, UriSchemeKeyedCollection baseAddresses)
        { 
            Fx.Assert(serviceDefinition != null, "caller must verify");

            this.serviceDefinition = serviceDefinition;
            base.InitializeDescription(baseAddresses); 

            foreach (Endpoint endpoint in serviceDefinition.Endpoints) 
            { 
                if (endpoint.Binding == null)
                { 
                    string endpointName = ContractValidationHelper.GetErrorMessageEndpointName(endpoint.Name);
                    string contractName = ContractValidationHelper.GetErrorMessageEndpointServiceContractName(endpoint.ServiceContractName);
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.MissingBindingInEndpoint(endpointName, contractName)));
                } 

                ServiceEndpoint serviceEndpoint = AddServiceEndpointCore(endpoint.ServiceContractName, endpoint.Binding, 
                        endpoint.GetAddress(this), endpoint.ListenUri, endpoint.BehaviorConfigurationName); 

                if (!string.IsNullOrEmpty(endpoint.Name)) 
                {
                    serviceEndpoint.Name = endpoint.Name;
                }
                serviceEndpoint.UnresolvedAddress = endpoint.AddressUri; 
                serviceEndpoint.UnresolvedListenUri = endpoint.ListenUri;
            } 
 
            this.PersistTimeout = defaultPersistTimeout;
            this.TrackTimeout = defaultTrackTimeout; 
            this.FilterResumeTimeout = defaultFilterResumeTimeout;
        }

        protected override void InitializeRuntime() 
        {
            if (base.Description != null) 
            { 
                FixupEndpoints();
                if(this.DurableInstancingOptions.ScopeName == null) 
                {
                    this.DurableInstancingOptions.ScopeName = XNamespace.Get(this.Description.Namespace).GetName(this.Description.Name);
                }
            } 

            base.InitializeRuntime(); 
 
            this.ServiceName = XNamespace.Get(this.Description.Namespace).GetName(this.Description.Name);
 
            // add a host-wide SendChannelCache (with default settings) if one doesn't exist
            this.workflowExtensions.EnsureChannelCache();

            // add a host-wide (free-threaded) CorrelationExtension based on our ServiceName 
            this.WorkflowExtensions.Add(new CorrelationExtension(this.DurableInstancingOptions.ScopeName));
 
            this.WorkflowExtensions.MakeReadOnly(); 

            // now calculate if IsLoadTransactionRequired 
            this.IsLoadTransactionRequired = WorkflowServiceInstance.IsLoadTransactionRequired(this);

            if (this.serviceDefinition != null)
            { 
                ValidateBufferedReceiveProperty();
                this.serviceDefinition.ResetServiceDescription(); 
            } 
        }
 
        protected override void OnOpen(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
            base.OnOpen(timeoutHelper.RemainingTime());
 
            this.durableInstanceManager.Open(timeoutHelper.RemainingTime()); 
        }
 
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new OpenAsyncResult(this, timeout, callback, state);
        } 

        protected override void OnEndOpen(IAsyncResult result) 
        { 
            OpenAsyncResult.End(result);
        } 

        protected override void OnClose(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 

            base.OnClose(timeoutHelper.RemainingTime()); 
 
            this.durableInstanceManager.Close(timeoutHelper.RemainingTime());
        } 

        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CloseAsyncResult(this, timeout, callback, state); 
        }
 
        protected override void OnEndClose(IAsyncResult result) 
        {
            CloseAsyncResult.End(result); 
        }

        protected override void OnAbort()
        { 
            base.OnAbort();
 
            this.durableInstanceManager.Abort(); 
        }
 
        internal void FaultServiceHostIfNecessary(Exception exception)
        {
            if (exception is InstancePersistenceException && !(exception is InstancePersistenceCommandException))
            { 
                this.Fault(exception);
            } 
        } 

        IAsyncResult BeginHostOpen(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return base.OnBeginOpen(timeout, callback, state);
        }
        void EndHostOpen(IAsyncResult result) 
        {
            base.OnEndOpen(result); 
        } 

        IAsyncResult BeginHostClose(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            return base.OnBeginClose(timeout, callback, state);
        }
        void EndHostClose(IAsyncResult result) 
        {
            base.OnEndClose(result); 
        } 

        void AddCorrelationQueryBehaviorToServiceEndpoint(ServiceEndpoint serviceEndpoint) 
        {
            Fx.Assert(serviceEndpoint != null, "Argument cannot be null!");
            Fx.Assert(serviceEndpoint.Contract != null, "ServiceEndpoint must have a contract!");
            Fx.Assert(this.serviceDefinition != null, "Missing WorkflowService!"); 
            Fx.Assert(!serviceEndpoint.Behaviors.Contains(correlationQueryBehaviorType),
                "ServiceEndpoint should not have CorrelationQueryBehavior before this point!"); 
 
            XName endpointContractName = XName.Get(serviceEndpoint.Contract.Name, serviceEndpoint.Contract.Namespace);
 
            Collection queries;
            if (this.correlationQueries != null && this.correlationQueries.TryGetValue(endpointContractName, out queries))
            {
                // Filter out duplicate CorrelationQueries in the collection. 
                // Currently, we only do reference comparison and Where message filter comparison.
                Collection uniqueQueries = new Collection(); 
                foreach (CorrelationQuery correlationQuery in queries) 
                {
                    if (!uniqueQueries.Contains(correlationQuery)) 
                    {
                        uniqueQueries.Add(correlationQuery);
                    }
                    else 
                    {
                        if (TD.DuplicateCorrelationQueryIsEnabled()) 
                        { 
                            TD.DuplicateCorrelationQuery(correlationQuery.Where.ToString());
                        } 
                    }
                }
                serviceEndpoint.Behaviors.Add(new CorrelationQueryBehavior(uniqueQueries) { ServiceContractName = endpointContractName });
            } 
            else if (CorrelationQueryBehavior.BindingHasDefaultQueries(serviceEndpoint.Binding))
            { 
                if (!serviceEndpoint.Behaviors.Contains(typeof(CorrelationQueryBehavior))) 
                {
                    serviceEndpoint.Behaviors.Add(new CorrelationQueryBehavior(new Collection()) { ServiceContractName = endpointContractName }); 
                }
            }
        }
 
        void FixupEndpoints()
        { 
            Fx.Assert(this.Description != null, "ServiceDescription cannot be null"); 

            Dictionary contractDescriptionDictionary = new Dictionary(); 
            foreach (ServiceEndpoint serviceEndpoint in this.Description.Endpoints)
            {
                if (this.serviceDefinition.AllowBufferedReceive)
                { 
                    // All application-level endpoints need to support ReceiveContext
                    SetupReceiveContextEnabledAttribute(serviceEndpoint); 
                } 

                // Need to add CorrelationQueryBehavior here so that endpoints added from config are included. 
                // It is possible that some endpoints already have CorrelationQueryBehavior from
                // the AddDefaultEndpoints code path. We should skip them.
                if (!serviceEndpoint.Behaviors.Contains(correlationQueryBehaviorType))
                { 
                    AddCorrelationQueryBehaviorToServiceEndpoint(serviceEndpoint);
                } 
 
                // Need to ensure that any WorkflowHostingEndpoints using the same contract type actually use the
                // same contractDescription instance since this is required by WCF. 
                if (serviceEndpoint is WorkflowHostingEndpoint)
                {
                    ContractDescription contract;
                    if (contractDescriptionDictionary.TryGetValue(serviceEndpoint.Contract.ContractType, out contract)) 
                    {
                        serviceEndpoint.Contract = contract; 
                    } 
                    else
                    { 
                        contractDescriptionDictionary[serviceEndpoint.Contract.ContractType] = serviceEndpoint.Contract;
                    }
                }
            } 

            if (this.serviceDefinition.AllowBufferedReceive && !this.Description.Behaviors.Contains(bufferedReceiveServiceBehaviorType)) 
            { 
                this.Description.Behaviors.Add(new BufferedReceiveServiceBehavior());
            } 
        }

        void SetupReceiveContextEnabledAttribute(ServiceEndpoint serviceEndpoint)
        { 
            if (BufferedReceiveServiceBehavior.IsWorkflowEndpoint(serviceEndpoint))
            { 
                foreach (OperationDescription operation in serviceEndpoint.Contract.Operations) 
                {
                    ReceiveContextEnabledAttribute behavior = operation.Behaviors.Find(); 
                    if (behavior == null)
                    {
                        operation.Behaviors.Add(new ReceiveContextEnabledAttribute() { ManualControl = true });
                    } 
                    else
                    { 
                        behavior.ManualControl = true; 
                    }
                } 
            }
        }

        void ValidateBufferedReceiveProperty() 
        {
            // Validate that the AttachedProperty is indeed being used when the behavior is also used 
            bool hasBehavior = this.Description.Behaviors.Contains(bufferedReceiveServiceBehaviorType); 
            if (hasBehavior && !this.serviceDefinition.AllowBufferedReceive)
            { 
                throw FxTrace.Exception.AsError(new InvalidOperationException(SR.BufferedReceiveBehaviorUsedWithoutProperty));
            }
        }
 
        // specialized WorkflowInstanceExtensionManager that can default in a SendMessageChannelCache
        class WorkflowServiceHostExtensions : WorkflowInstanceExtensionManager 
        { 
            bool hasChannelCache;
 
            public WorkflowServiceHostExtensions()
                : base()
            {
            } 

            public override void Add(Func extensionCreationFunction) 
            { 
                if (TypeHelper.AreTypesCompatible(typeof(T), typeof(SendMessageChannelCache)))
                { 
                    this.hasChannelCache = true;
                }
                base.Add(extensionCreationFunction);
            } 

            public override void Add(object singletonExtension) 
            { 
                if (singletonExtension is SendMessageChannelCache)
                { 
                    this.hasChannelCache = true;
                }
                base.Add(singletonExtension);
            } 

            public void EnsureChannelCache() 
            { 
                if (!this.hasChannelCache)
                { 
                    Add(new SendMessageChannelCache());
                    this.hasChannelCache = true;
                }
            } 
        }
 
        class OpenAsyncResult : AsyncResult 
        {
            static AsyncCompletion handleDurableInstanceManagerEndOpen = new AsyncCompletion(HandleDurableInstanceManagerEndOpen); 
            static AsyncCompletion handleEndHostOpen = new AsyncCompletion(HandleEndHostOpen);

            TimeoutHelper timeoutHelper;
            WorkflowServiceHost host; 

            public OpenAsyncResult(WorkflowServiceHost host, TimeSpan timeout, AsyncCallback callback, object state) 
                : base(callback, state) 
            {
                this.timeoutHelper = new TimeoutHelper(timeout); 
                this.host = host;

                if (HostOpen())
                { 
                    Complete(true);
                } 
            } 

            bool OpenDurableInstanceManager() 
            {
                IAsyncResult result = this.host.durableInstanceManager.BeginOpen(
                    this.timeoutHelper.RemainingTime(), base.PrepareAsyncCompletion(handleDurableInstanceManagerEndOpen), this);
                return SyncContinue(result); 
            }
 
            bool HostOpen() 
            {
                IAsyncResult result = this.host.BeginHostOpen( 
                    this.timeoutHelper.RemainingTime(), base.PrepareAsyncCompletion(handleEndHostOpen), this);
                return SyncContinue(result);
            }
 
            static bool HandleDurableInstanceManagerEndOpen(IAsyncResult result)
            { 
                OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState; 

                thisPtr.host.durableInstanceManager.EndOpen(result); 
                return true;
            }

            static bool HandleEndHostOpen(IAsyncResult result) 
            {
                OpenAsyncResult thisPtr = (OpenAsyncResult)result.AsyncState; 
 
                thisPtr.host.EndHostOpen(result);
 
                return thisPtr.OpenDurableInstanceManager();
            }

            public static void End(IAsyncResult result) 
            {
                AsyncResult.End(result); 
            } 
        }
 
        class CloseAsyncResult : AsyncResult
        {
            static AsyncCompletion handleDurableInstanceManagerEndClose = new AsyncCompletion(HandleDurableInstanceManagerEndClose);
            static AsyncCompletion handleEndHostClose = new AsyncCompletion(HandleEndHostClose); 

            TimeoutHelper timeoutHelper; 
            WorkflowServiceHost host; 

            public CloseAsyncResult(WorkflowServiceHost host, TimeSpan timeout, AsyncCallback callback, object state) 
                : base(callback, state)
            {
                this.timeoutHelper = new TimeoutHelper(timeout);
                this.host = host; 

                if (CloseHost()) 
                { 
                    Complete(true);
                } 
            }

            bool CloseDurableInstanceManager()
            { 
                IAsyncResult result = this.host.durableInstanceManager.BeginClose(
                    this.timeoutHelper.RemainingTime(), base.PrepareAsyncCompletion(handleDurableInstanceManagerEndClose), this); 
                return SyncContinue(result); 
            }
 
            bool CloseHost()
            {
                IAsyncResult result = this.host.BeginHostClose(
                    this.timeoutHelper.RemainingTime(), base.PrepareAsyncCompletion(handleEndHostClose), this); 
                return SyncContinue(result);
            } 
 
            static bool HandleDurableInstanceManagerEndClose(IAsyncResult result)
            { 
                CloseAsyncResult thisPtr = (CloseAsyncResult)result.AsyncState;

                thisPtr.host.durableInstanceManager.EndClose(result);
                return true; 
            }
 
            static bool HandleEndHostClose(IAsyncResult result) 
            {
                CloseAsyncResult thisPtr = (CloseAsyncResult)result.AsyncState; 

                thisPtr.host.EndHostClose(result);
                return thisPtr.CloseDurableInstanceManager();
            } 

            public static void End(IAsyncResult result) 
            { 
                AsyncResult.End(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