ServiceHost.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / ServiceHost.cs / 1 / ServiceHost.cs

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

namespace System.ServiceModel 
{
    using System; 
    using System.ServiceModel.Administration; 
    using System.ServiceModel.Dispatcher;
    using System.ServiceModel.Description; 
    using System.Text;
    using System.ServiceModel.Configuration;
    using System.Collections.Generic;
    using System.Collections.ObjectModel; 
    using System.Diagnostics;
    using System.Globalization; 
    using System.Runtime.Serialization; 
    using System.Runtime.InteropServices;
    using System.ServiceModel.Channels; 
    using System.ServiceModel.Diagnostics;
    using System.Threading;
    using System.Xml;
    using System.Security; 

    public abstract class ServiceHostBase : CommunicationObject, IExtensibleObject, IDisposable 
    { 
        internal static readonly Uri EmptyUri = new Uri(string.Empty, UriKind.RelativeOrAbsolute);
 
        bool initializeDescriptionHasFinished;
        UriSchemeKeyedCollection baseAddresses;
        ChannelDispatcherCollection channelDispatchers;
        TimeSpan closeTimeout = ServiceDefaults.ServiceHostCloseTimeout; 
        ServiceDescription description;
        ExtensionCollection extensions; 
        ReadOnlyCollection externalBaseAddresses; 
        IDictionary implementedContracts;
        IInstanceContextManager instances; 
        TimeSpan openTimeout = ServiceDefaults.OpenTimeout;
        ServicePerformanceCounters servicePerformanceCounters;
        DefaultPerformanceCounters defaultPerformanceCounters;
        ServiceThrottle serviceThrottle; 
        ServiceCredentials readOnlyCredentials;
        ServiceAuthorizationBehavior readOnlyAuthorization; 
 
        public event EventHandler UnknownMessageReceived;
 
        protected ServiceHostBase()
        {
            this.baseAddresses = new UriSchemeKeyedCollection(this.ThisLock);
            this.channelDispatchers = new ChannelDispatcherCollection(this, this.ThisLock); 
            this.extensions = new ExtensionCollection(this, this.ThisLock);
            this.instances = new InstanceContextManager(this.ThisLock); 
            this.serviceThrottle = new ServiceThrottle(this); 
            this.TraceOpenAndClose = true;
            this.Faulted += new EventHandler(OnServiceHostFaulted); 
        }

        public ServiceAuthorizationBehavior Authorization
        { 
            get
            { 
                if (this.Description == null) 
                {
                    return null; 
                }
                else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening)
                {
                    return EnsureAuthorization(this.Description); 
                }
                else 
                { 
                    return this.readOnlyAuthorization;
                } 
            }
        }

        public ReadOnlyCollection BaseAddresses 
        {
            get 
            { 
                externalBaseAddresses = new ReadOnlyCollection(new List(this.baseAddresses));
                return externalBaseAddresses; 
            }
        }

        public ChannelDispatcherCollection ChannelDispatchers 
        {
            get { return this.channelDispatchers; } 
        } 

        public TimeSpan CloseTimeout 
        {
            get { return this.closeTimeout; }
            set
            { 
                if (value < TimeSpan.Zero)
                { 
                    string message = SR.GetString(SR.SFxTimeoutOutOfRange0); 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", message));
                } 
                if (TimeoutHelper.IsTooLarge(value))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
                } 

                lock (this.ThisLock) 
                { 
                    this.ThrowIfClosedOrOpened();
                    this.closeTimeout = value; 
                }
            }
        }
 
        internal ServicePerformanceCounters Counters
        { 
            get 
            {
                return this.servicePerformanceCounters; 
            }
            set
            {
                this.servicePerformanceCounters = value; 
            }
        } 
 
        internal DefaultPerformanceCounters DefaultCounters
        { 
            get
            {
                return this.defaultPerformanceCounters;
            } 
            set
            { 
                this.defaultPerformanceCounters = value; 
            }
        } 

        public ServiceCredentials Credentials
        {
            get 
            {
                if (this.Description == null) 
                { 
                    return null;
                } 
                else if (this.State == CommunicationState.Created || this.State == CommunicationState.Opening)
                {
                    return EnsureCredentials(this.Description);
                } 
                else
                { 
                    return this.readOnlyCredentials; 
                }
            } 
        }

        protected override TimeSpan DefaultCloseTimeout
        { 
            get { return this.CloseTimeout; }
        } 
 
        protected override TimeSpan DefaultOpenTimeout
        { 
            get { return this.OpenTimeout; }
        }

        public ServiceDescription Description 
        {
            get { return this.description; } 
        } 

        public IExtensionCollection Extensions 
        {
            get { return this.extensions; }
        }
 
        protected IDictionary ImplementedContracts
        { 
            get { return this.implementedContracts; } 
        }
 
        internal UriSchemeKeyedCollection InternalBaseAddresses
        {
            get { return this.baseAddresses; }
        } 

        public int ManualFlowControlLimit 
        { 
            get { return this.ServiceThrottle.ManualFlowControlLimit; }
            set { this.ServiceThrottle.ManualFlowControlLimit = value; } 
        }

        public TimeSpan OpenTimeout
        { 
            get { return this.openTimeout; }
            set 
            { 
                if (value < TimeSpan.Zero)
                { 
                    string message = SR.GetString(SR.SFxTimeoutOutOfRange0);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", message));
                }
                if (TimeoutHelper.IsTooLarge(value)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", SR.GetString(SR.SFxTimeoutOutOfRangeTooBig))); 
                } 

                lock (this.ThisLock) 
                {
                    this.ThrowIfClosedOrOpened();
                    this.openTimeout = value;
                } 
            }
        } 
 
        internal ServiceThrottle ServiceThrottle
        { 
            get
            {
                return this.serviceThrottle;
            } 
        }
 
        internal virtual object DisposableInstance 
        {
            get 
            {
                return null;
            }
        } 

        protected void AddBaseAddress(Uri baseAddress) 
        { 
            if (this.initializeDescriptionHasFinished)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(
                    SR.GetString(SR.SFxCannotCallAddBaseAddress)));
            }
            this.baseAddresses.Add(baseAddress); 
        }
 
        public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address) 
        {
            return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 
        }

        public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, string address, Uri listenUri)
        { 
            if (address == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address")); 
            }
 
            ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute));
            if (listenUri != null)
            {
                listenUri = MakeAbsoluteUri(listenUri, binding); 
                endpoint.ListenUri = listenUri;
            } 
            return endpoint; 
        }
 
        public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address)
        {
            return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null);
        } 

        public ServiceEndpoint AddServiceEndpoint(string implementedContract, Binding binding, Uri address, Uri listenUri) 
        { 
            if (address == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address"));
            }

            if (binding == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("binding")); 
            } 

            if (implementedContract == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract"));
            }
 
            if (this.State != CommunicationState.Created && this.State != CommunicationState.Opening)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointAfterOpen))); 
            }
 
            if (this.Description == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotAddEndpointWithoutDescription)));
            } 

            Uri via = this.MakeAbsoluteUri(address, binding); 
 
            ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.implementedContracts));
            ContractDescription contract = configLoader.LookupContract(implementedContract, this.Description.Name); 

            ServiceEndpoint serviceEndpoint = new ServiceEndpoint(contract, binding, new EndpointAddress(via));
            this.Description.Endpoints.Add(serviceEndpoint);
            if (listenUri != null) 
            {
                listenUri = MakeAbsoluteUri(listenUri, binding); 
                serviceEndpoint.ListenUri = listenUri; 
            }
            return serviceEndpoint; 
        }

        internal Uri MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding)
        { 
            return MakeAbsoluteUri(relativeOrAbsoluteUri, binding, this.InternalBaseAddresses);
        } 
 
        internal static Uri MakeAbsoluteUri(Uri relativeOrAbsoluteUri, Binding binding, UriSchemeKeyedCollection baseAddresses)
        { 
            Uri result = relativeOrAbsoluteUri;
            if (!result.IsAbsoluteUri)
            {
                if (binding.Scheme == string.Empty) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCustomBindingWithoutTransport))); 
                } 
                result = GetVia(binding.Scheme, result, baseAddresses);
                if (result == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxEndpointNoMatchingScheme, binding.Scheme, binding.Name, GetBaseAddressSchemes(baseAddresses))));
                }
            } 
            return result;
        } 
 
        protected virtual void ApplyConfiguration()
        { 
            if (this.Description == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotApplyConfigurationWithoutDescription)));
            } 

            ConfigLoader configLoader = new ConfigLoader(GetContractResolver(implementedContracts)); 
            LoadConfigurationSectionInternal(configLoader, this.Description, this.Description.ConfigurationName); 

            EnsureAuthorization(description); 
            EnsureDebug(description);
        }

        internal virtual void BindInstance(InstanceContext instance) 
        {
            this.instances.Add(instance); 
            if (null != this.servicePerformanceCounters) 
            {
                lock (this.ThisLock) 
                {
                    if (null != this.servicePerformanceCounters)
                    {
                        this.servicePerformanceCounters.ServiceInstanceCreated(); 
                    }
                } 
            } 
        }
 
        void IDisposable.Dispose()
        {
            Close();
        } 

        protected abstract ServiceDescription CreateDescription(out IDictionary implementedContracts); 
 
        protected virtual void InitializeRuntime()
        { 
            if (this.Description == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotInitializeRuntimeWithoutDescription)));
            } 

            DispatcherBuilder dispatcherBuilder = new DispatcherBuilder(); 
            dispatcherBuilder.InitializeServiceHost(description, this); 

            SecurityValidationBehavior.Instance.AfterBuildTimeValidation(description); 
        }

        ServiceAuthorizationBehavior EnsureAuthorization(ServiceDescription description)
        { 
            DiagnosticUtility.DebugAssert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, "");
            ServiceAuthorizationBehavior a = description.Behaviors.Find(); 
 
            if (a == null)
            { 
                a = new ServiceAuthorizationBehavior();
                description.Behaviors.Add(a);
            }
 
            return a;
        } 
 
        ServiceDebugBehavior EnsureDebug(ServiceDescription description)
        { 
            DiagnosticUtility.DebugAssert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, "");
            ServiceDebugBehavior m = description.Behaviors.Find();

            if (m == null) 
            {
                m = new ServiceDebugBehavior(); 
                description.Behaviors.Add(m); 
            }
 
            return m;
        }

 
        ServiceCredentials EnsureCredentials(ServiceDescription description)
        { 
            DiagnosticUtility.DebugAssert(this.State == CommunicationState.Created || this.State == CommunicationState.Opening, ""); 
            ServiceCredentials c = description.Behaviors.Find();
 
            if (c == null)
            {
                c = new ServiceCredentials();
                description.Behaviors.Add(c); 
            }
 
            return c; 
        }
 
        internal void FaultInternal()
        {
            this.Fault();
        } 

        internal string GetBaseAddressSchemes() 
        { 
            return GetBaseAddressSchemes(baseAddresses);
        } 

        internal static String GetBaseAddressSchemes(UriSchemeKeyedCollection uriSchemeKeyedCollection)
        {
            StringBuilder buffer = new StringBuilder(); 
            bool firstScheme = true;
            foreach (Uri address in uriSchemeKeyedCollection) 
            { 
                if (firstScheme)
                { 
                    buffer.Append(address.Scheme);
                    firstScheme = false;
                }
                else 
                {
                    buffer.Append(CultureInfo.CurrentCulture.TextInfo.ListSeparator).Append(address.Scheme); 
                } 
            }
            return buffer.ToString(); 
        }

        internal ReadOnlyCollection GetInstanceContexts()
        { 
            return new ReadOnlyCollection(Array.AsReadOnly(instances.ToArray()));
        } 
 
        internal virtual IContractResolver GetContractResolver(IDictionary implementedContracts)
        { 
            ServiceAndBehaviorsContractResolver resolver = new ServiceAndBehaviorsContractResolver(new ImplementedContractsContractResolver(implementedContracts));
            resolver.AddBehaviorContractsToResolver(this.description==null ? null : this.description.Behaviors);
            return resolver;
        } 

 
 
        internal static Uri GetUri(Uri baseUri, Uri relativeUri)
        { 
            return GetUri(baseUri, relativeUri.OriginalString);
        }

        internal static Uri GetUri(Uri baseUri, string path) 
        {
            if (path.StartsWith("/", StringComparison.Ordinal) || path.StartsWith("\\", StringComparison.Ordinal)) 
            { 
                int i = 1;
                for (; i < path.Length; ++i) 
                {
                    if (path[i] != '/' && path[i] != '\\')
                    {
                        break; 
                    }
                } 
                path = path.Substring(i); 
            }
 
            // VSWhidbey#541152: new Uri(Uri, string.Empty) is broken
            if (path.Length == 0)
                return baseUri;
 
            if (!baseUri.AbsoluteUri.EndsWith("/", StringComparison.Ordinal))
            { 
                baseUri = new Uri(baseUri.AbsoluteUri + "/"); 
            }
            return new Uri(baseUri, path); 
        }

        internal Uri GetVia(string scheme, Uri address)
        { 
            return ServiceHost.GetVia(scheme, address, InternalBaseAddresses);
        } 
 
        internal static Uri GetVia(string scheme, Uri address, UriSchemeKeyedCollection baseAddresses)
        { 
            Uri via = address;
            if (!via.IsAbsoluteUri)
            {
                if (!baseAddresses.Contains(scheme)) 
                {
                    return null; 
                } 

                via = GetUri(baseAddresses[scheme], address); 
            }
            return via;
        }
 
        public int IncrementManualFlowControlLimit(int incrementBy)
        { 
            return this.ServiceThrottle.IncrementManualFlowControlLimit(incrementBy); 
        }
 
        protected void InitializeDescription(UriSchemeKeyedCollection baseAddresses)
        {
            foreach (Uri baseAddress in baseAddresses)
            { 
                this.baseAddresses.Add(baseAddress);
            } 
            IDictionary implementedContracts = null; 
            ServiceDescription description = CreateDescription(out implementedContracts);
            this.description = description; 
            this.implementedContracts = implementedContracts;

            ApplyConfiguration();
            this.initializeDescriptionHasFinished = true; 
        }
 
        protected void LoadConfigurationSection(ServiceElement serviceSection) 
        {
            if (serviceSection == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("serviceSection");
            }
            if (this.Description == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostBaseCannotLoadConfigurationSectionWithoutDescription))); 
            } 

            ConfigLoader configLoader = new ConfigLoader(GetContractResolver(this.ImplementedContracts)); 
            LoadConfigurationSectionInternal(configLoader, this.Description, serviceSection);
        }

        internal void LoadConfigurationSectionHelper(Uri baseAddress) 
        {
            this.AddBaseAddress(baseAddress); 
        } 

        ///  
        /// Critical - calls LookupService which is critical
        /// Safe - doesn't leak ServiceElement out of SecurityCritical code
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        void LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, string configurationName)
        { 
            ServiceElement serviceSection = configLoader.LookupService(configurationName); 
            LoadConfigurationSectionInternal(configLoader, description, serviceSection);
        } 

        /// 
        /// Critical - handles a ServiceElement, which should not be leaked out of SecurityCritical code
        /// Safe - doesn't leak ServiceElement out of SecurityCritical code 
        /// 
        [SecurityCritical, SecurityTreatAsSafe] 
        void LoadConfigurationSectionInternal(ConfigLoader configLoader, ServiceDescription description, ServiceElement serviceSection) 
        {
            // caller must validate arguments before calling 
            configLoader.LoadServiceDescription(this, description, serviceSection, this.LoadConfigurationSectionHelper);
        }

        protected sealed override void OnAbort() 
        {
            instances.Abort(); 
 
            foreach (ChannelDispatcherBase dispatcher in this.ChannelDispatchers)
            { 
                if (dispatcher.Listener != null)
                {
                    dispatcher.Listener.Abort();
                } 
                dispatcher.Abort();
            } 
            ThreadTrace.StopTracing(); 
        }
 
        internal void OnAddChannelDispatcher(ChannelDispatcherBase channelDispatcher)
        {
            lock (this.ThisLock)
            { 
                this.ThrowIfClosedOrOpened();
                channelDispatcher.AttachInternal(this); 
                channelDispatcher.Faulted += new EventHandler(OnChannelDispatcherFaulted); 
            }
        } 

        protected sealed override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            return new CloseAsyncResult(timeout, callback, state, this); 
        }
 
        void OnBeginOpen() 
        {
            this.TraceBaseAddresses(); 
            MessageLogger.EnsureInitialized(); //force config validation instead of waiting for the first message exchange
            InitializeRuntime();
        }
 
        protected sealed override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            this.OnBeginOpen();
 
            return new OpenCollectionAsyncResult(timeout, callback, state, this.SnapshotChannelDispatchers());
        }

        protected override void OnClose(TimeSpan timeout) 
        {
            try 
            { 
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
 
                if (ManagementExtension.IsEnabled && null != this.Description)
                {
                    ManagementExtension.OnServiceClosing(this);
                } 

                for (int i = 0; i < this.ChannelDispatchers.Count; i++) 
                { 
                    ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
                    if (dispatcher.Listener != null) 
                    {
                        dispatcher.Listener.Close(timeoutHelper.RemainingTime());
                    }
                } 

                for (int i = 0; i < this.ChannelDispatchers.Count; i++) 
                { 
                    ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
                    dispatcher.CloseInput(); 
                }

                // Wait for existing work to complete
                instances.CloseInput(timeoutHelper.RemainingTime()); 

                // Close instances (closes contexts/channels) 
                instances.Close(timeoutHelper.RemainingTime()); 

                // Close dispatchers 
                for (int i = 0; i < this.ChannelDispatchers.Count; i++)
                {
                    ChannelDispatcherBase dispatcher = this.ChannelDispatchers[i];
                    dispatcher.Close(timeoutHelper.RemainingTime()); 
                }
 
                this.ReleasePerformanceCounters(); 
                this.TraceBaseAddresses();
                ThreadTrace.StopTracing(); 
            }
            catch (TimeoutException e)
            {
                if (DiagnosticUtility.ShouldTraceWarning) 
                {
                    TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostTimeoutOnClose, this, e); 
                } 
                this.Abort();
            } 

        }

        void TraceBaseAddresses() 
        {
            if (DiagnosticUtility.ShouldTraceInformation && this.baseAddresses != null 
                && this.baseAddresses.Count > 0) 
            {
                TraceUtility.TraceEvent(TraceEventType.Information, 
                    TraceCode.ServiceHostBaseAddresses,
                    new CollectionTraceRecord("BaseAddresses", "Address", this.baseAddresses),
                    this, null);
            } 
        }
 
        protected override void OnEndClose(IAsyncResult result) 
        {
            try 
            {
                CloseAsyncResult.End(result);
                this.ReleasePerformanceCounters();
                this.TraceBaseAddresses(); 
                ThreadTrace.StopTracing();
            } 
            catch (TimeoutException e) 
            {
                if (DiagnosticUtility.ShouldTraceWarning) 
                {
                    TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostTimeoutOnClose, this, e);
                }
                this.Abort(); 
            }
        } 
 
        protected sealed override void OnEndOpen(IAsyncResult result)
        { 
            OpenCollectionAsyncResult.End(result);
        }

        protected sealed override void OnOpen(TimeSpan timeout) 
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            this.OnBeginOpen(); 

            for (int i=0; i();
                if (c != null)
                { 
                    ServiceCredentials credentialsCopy = c.Clone();
                    credentialsCopy.MakeReadOnly(); 
                    this.readOnlyCredentials = credentialsCopy; 
                }
 
                ServiceAuthorizationBehavior authorization = description.Behaviors.Find();
                if (authorization != null)
                {
                    ServiceAuthorizationBehavior authorizationCopy = authorization.Clone(); 
                    authorizationCopy.MakeReadOnly();
                    this.readOnlyAuthorization = authorizationCopy; 
                } 

                if (ManagementExtension.IsEnabled) 
                {
                    ManagementExtension.OnServiceOpened(this);
                }
            } 
            base.OnOpened();
        } 
 
        internal void OnRemoveChannelDispatcher(ChannelDispatcherBase channelDispatcher)
        { 
            lock (this.ThisLock)
            {
                this.ThrowIfClosedOrOpened();
                channelDispatcher.DetachInternal(this); 
            }
        } 
 
        void OnChannelDispatcherFaulted(object sender, EventArgs e)
        { 
            this.Fault();
        }

        void OnServiceHostFaulted(object sender, EventArgs args) 
        {
            if (DiagnosticUtility.ShouldTraceWarning) 
            { 
                TraceUtility.TraceEvent(TraceEventType.Warning, TraceCode.ServiceHostFaulted, this);
            } 

            foreach (ICommunicationObject channelDispatcher in this.SnapshotChannelDispatchers())
            {
                if (channelDispatcher.State == CommunicationState.Opened) 
                {
                    channelDispatcher.Abort(); 
                } 
            }
        } 

        internal void RaiseUnknownMessageReceived(Message message)
        {
            try 
            {
                EventHandler handler = UnknownMessageReceived; 
                if (handler != null) 
                {
                    handler(this, new UnknownMessageReceivedEventArgs(message)); 
                }
            }
            catch (Exception e)
            { 
                if (DiagnosticUtility.IsFatal(e))
                    throw; 
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperCallback(e);
            } 
        }

        protected void ReleasePerformanceCounters()
        { 
            if (this.servicePerformanceCounters != null)
            { 
                lock (this.ThisLock) 
                {
                    if (this.servicePerformanceCounters != null) 
                    {
                        PerformanceCounters.ReleasePerformanceCountersForService(this.servicePerformanceCounters, false);
                        this.servicePerformanceCounters = null;
                    } 
                }
            } 
            if (this.defaultPerformanceCounters != null) 
            {
                lock (this.ThisLock) 
                {
                    if (this.defaultPerformanceCounters != null)
                    {
                        PerformanceCounters.ReleasePerformanceCountersForService(this.defaultPerformanceCounters, true); 
                        this.defaultPerformanceCounters = null;
                    } 
                } 
            }
        } 

        ICommunicationObject[] SnapshotChannelDispatchers()
        {
            lock (this.ThisLock) 
            {
                ICommunicationObject[] array = new ICommunicationObject[this.ChannelDispatchers.Count]; 
                for (int i=0; i listeners = new List(); 
                for (int i=0; i channelDispatchers = this.serviceHost.SnapshotChannelDispatchers();
                AsyncCallback callback = DiagnosticUtility.ThunkAsyncCallback(this.CloseChannelDispatchersCallback); 
                TimeSpan timeout = this.timeoutHelper.RemainingTime(); 
                Exception exception = null;
                IAsyncResult result = null; 
                try
                {
                    result = new CloseCollectionAsyncResult(timeout, callback, this, channelDispatchers);
                } 
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e) || completedSynchronously) 
                    {
                        throw; 
                    }
                    exception = e;
                }
 
                if (exception != null)
                { 
                    this.CallComplete(completedSynchronously, exception); 
                }
                else if (result.CompletedSynchronously) 
                {
                    this.FinishCloseChannelDispatchers(result, completedSynchronously);
                }
            } 

            void CloseChannelDispatchersCallback(IAsyncResult result) 
            { 
                if (!result.CompletedSynchronously)
                { 
                    ((CloseAsyncResult)result.AsyncState).FinishCloseChannelDispatchers(result, false);
                }
            }
 
            void FinishCloseChannelDispatchers(IAsyncResult result, bool completedSynchronously)
            { 
                Exception exception = null; 
                try
                { 
                    CloseCollectionAsyncResult.End(result);
                }
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e) || completedSynchronously)
                    { 
                        throw; 
                    }
                    exception = e; 
                }

                this.CallComplete(completedSynchronously, exception);
            } 

            void CallComplete(bool completedSynchronously, Exception exception) 
            { 
                this.Complete(completedSynchronously, exception);
            } 

            public static void End(IAsyncResult result)
            {
                AsyncResult.End(result); 
            }
        } 
 
        class ImplementedContractsContractResolver : IContractResolver
        { 
            IDictionary implementedContracts;

            public ImplementedContractsContractResolver(IDictionary implementedContracts)
            { 
                this.implementedContracts = implementedContracts;
            } 
 
            public ContractDescription ResolveContract(string contractName)
            { 
                return this.implementedContracts != null && this.implementedContracts.ContainsKey(contractName) ? this.implementedContracts[contractName] : null;
            }
        }
 
        internal class ServiceAndBehaviorsContractResolver : IContractResolver
        { 
            IContractResolver serviceResolver; 
            Dictionary behaviorContracts;
 
            public Dictionary BehaviorContracts
            {
                get { return behaviorContracts; }
            } 

            public ServiceAndBehaviorsContractResolver(IContractResolver serviceResolver) 
            { 
                this.serviceResolver = serviceResolver;
                behaviorContracts = new Dictionary(); 
            }

            public ContractDescription ResolveContract(string contractName)
            { 
                ContractDescription contract = serviceResolver.ResolveContract(contractName);
 
                if (contract == null) 
                {
                    contract = this.behaviorContracts.ContainsKey(contractName) ? this.behaviorContracts[contractName] : null; 
                }

                return contract;
            } 

            public void AddBehaviorContractsToResolver(KeyedByTypeCollection behaviors) 
            { 
                // It would be nice to make this loop over all Behaviors... someday.
                if (behaviors != null && behaviors.Contains(typeof(ServiceMetadataBehavior))) 
                {
                    behaviors.Find().AddImplementedContracts(this);
                }
            } 
        }
    } 
 
    public class ServiceHost : ServiceHostBase
    { 
        object singletonInstance;
        Type serviceType;
        ReflectedContractCollection reflectedContracts;
        IDisposable disposableInstance; 

        protected ServiceHost() 
        { 
        }
 
        public ServiceHost(Type serviceType, params Uri[] baseAddresses)
        {
            if (serviceType == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType"));
            } 
 
            this.serviceType = serviceType;
            using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null) 
            {
                if (DiagnosticUtility.ShouldUseActivity)
                {
                    ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct); 
                }
 
                InitializeDescription(serviceType, new UriSchemeKeyedCollection(baseAddresses)); 
            }
        } 

        public ServiceHost(object singletonInstance, params Uri[] baseAddresses)
        {
            if (singletonInstance == null) 
            {
                throw new ArgumentNullException("singletonInstance"); 
            } 

            this.singletonInstance = singletonInstance; 
            this.serviceType = singletonInstance.GetType();
            using (ServiceModelActivity activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
            {
                if (DiagnosticUtility.ShouldUseActivity) 
                {
                    ServiceModelActivity.Start(activity, SR.GetString(SR.ActivityConstructServiceHost, serviceType.FullName), ActivityType.Construct); 
                } 

                InitializeDescription(singletonInstance, new UriSchemeKeyedCollection(baseAddresses)); 
            }
        }

        public object SingletonInstance 
        {
            get 
            { 
                return this.singletonInstance;
            } 
        }

        internal override object DisposableInstance
        { 
            get
            { 
                return this.disposableInstance; 
            }
        } 

        public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address)
        {
            return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 
        }
 
        public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, string address, Uri listenUri) 
        {
            if (address == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("address"));
            }
 
            ServiceEndpoint endpoint = this.AddServiceEndpoint(implementedContract, binding, new Uri(address, UriKind.RelativeOrAbsolute));
            if (listenUri != null) 
            { 
                listenUri = MakeAbsoluteUri(listenUri, binding);
                endpoint.ListenUri = listenUri; 
            }
            return endpoint;
        }
 
        public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address)
        { 
            return this.AddServiceEndpoint(implementedContract, binding, address, (Uri)null); 
        }
 
        public ServiceEndpoint AddServiceEndpoint(Type implementedContract, Binding binding, Uri address, Uri listenUri)
        {
            if (implementedContract == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("implementedContract"));
            } 
 
            if (!implementedContract.IsDefined(typeof(ServiceContractAttribute), false))
            { 
#pragma warning suppress 56506 // implementedContract is never null at this point
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxServiceContractAttributeNotFound, implementedContract.FullName)));
            }
 
            if (this.reflectedContracts == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractsNotInitialized1, implementedContract.FullName))); 
            }
 
            ReflectedAndBehaviorContractCollection reflectedAndBehaviorContracts = new ReflectedAndBehaviorContractCollection(this.reflectedContracts, this.Description.Behaviors);

            if (!reflectedAndBehaviorContracts.Contains(implementedContract))
            { 
                if (implementedContract == typeof(IMetadataExchange))
#pragma warning suppress 56506 // ServiceType is never null at this point 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFoundIMetadataExchange, this.serviceType.FullName))); 
                else
#pragma warning suppress 56506 // implementedContract and ServiceType are never null at this point 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, this.serviceType.FullName)));
            }

            ServiceEndpoint endpoint = AddServiceEndpoint(reflectedAndBehaviorContracts.GetConfigKey(implementedContract), binding, address); 
            if (listenUri != null)
            { 
                listenUri = MakeAbsoluteUri(listenUri, binding); 
                endpoint.ListenUri = listenUri;
            } 
            return endpoint;
        }

        internal override string CloseActivityName 
        {
            get { return SR.GetString(SR.ActivityCloseServiceHost, this.serviceType.FullName); } 
        } 

        internal override string OpenActivityName 
        {
            get { return SR.GetString(SR.ActivityOpenServiceHost, this.serviceType.FullName); }
        }
 
        protected override ServiceDescription CreateDescription(out IDictionary implementedContracts)
        { 
            if (this.serviceType == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxServiceHostCannotCreateDescriptionWithoutServiceType))); 
            }

            ServiceDescription description;
            if (this.SingletonInstance != null) 
            {
                description = ServiceDescription.GetService(this.SingletonInstance); 
            } 
            else
            { 
                description = ServiceDescription.GetService(this.serviceType);
            }
            ServiceBehaviorAttribute serviceBehavior = description.Behaviors.Find();
            object serviceInstanceUsedAsABehavior = serviceBehavior.GetWellKnownSingleton(); 
            if (serviceInstanceUsedAsABehavior == null)
            { 
                serviceInstanceUsedAsABehavior = serviceBehavior.GetHiddenSingleton(); 
                this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable;
            } 

            if ((typeof(IServiceBehavior).IsAssignableFrom(this.serviceType) || typeof(IContractBehavior).IsAssignableFrom(this.serviceType))
                && serviceInstanceUsedAsABehavior == null)
            { 
                serviceInstanceUsedAsABehavior = ServiceDescription.CreateImplementation(this.serviceType);
                this.disposableInstance = serviceInstanceUsedAsABehavior as IDisposable; 
            } 

            if (this.SingletonInstance == null) 
            {
                if (serviceInstanceUsedAsABehavior is IServiceBehavior)
                {
                    description.Behaviors.Add((IServiceBehavior)serviceInstanceUsedAsABehavior); 
                }
            } 
 
            ReflectedContractCollection reflectedContracts = new ReflectedContractCollection();
            List interfaces = ServiceReflector.GetInterfaces(this.serviceType); 
            for (int i = 0; i < interfaces.Count; i++)
            {
                Type contractType = interfaces[i];
                if (!reflectedContracts.Contains(contractType)) 
                {
                    ContractDescription contract = null; 
                    if (serviceInstanceUsedAsABehavior != null) 
                    {
                        contract = ContractDescription.GetContract(contractType, serviceInstanceUsedAsABehavior); 
                    }
                    else
                    {
                        contract = ContractDescription.GetContract(contractType, this.serviceType); 
                    }
 
                    reflectedContracts.Add(contract); 
                    Collection inheritedContracts = contract.GetInheritedContracts();
                    for (int j = 0; j < inheritedContracts.Count; j++) 
                    {
                        ContractDescription inheritedContract = inheritedContracts[j];
                        if (!reflectedContracts.Contains(inheritedContract.ContractType))
                        { 
                            reflectedContracts.Add(inheritedContract);
                        } 
                    } 
                }
            } 
            this.reflectedContracts = reflectedContracts;

            implementedContracts = reflectedContracts.ToImplementedContracts();
            return description; 
        }
 
        protected void InitializeDescription(object singletonInstance, UriSchemeKeyedCollection baseAddresses) 
        {
            if (singletonInstance == null) 
            {
                throw new ArgumentNullException("singletonInstance");
            }
 
            this.singletonInstance = singletonInstance;
            InitializeDescription(singletonInstance.GetType(), baseAddresses); 
        } 

        protected void InitializeDescription(Type serviceType, UriSchemeKeyedCollection baseAddresses) 
        {
            if (serviceType == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("serviceType")); 
            }
 
            this.serviceType = serviceType; 

            base.InitializeDescription(baseAddresses); 
        }

        protected override void OnClosed()
        { 
            base.OnClosed();
            if (this.disposableInstance != null) 
            { 
                this.disposableInstance.Dispose();
            } 
        }

        class ReflectedContractCollection : KeyedCollection
        { 
            public ReflectedContractCollection()
                : base(null, 4) 
            { 
            }
 
            protected override Type GetKeyForItem(ContractDescription item)
            {
                if (item == null)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("item"); 

                return item.ContractType; 
            } 

            public IDictionary ToImplementedContracts() 
            {
                Dictionary implementedContracts = new Dictionary();
                foreach (ContractDescription contract in this.Items)
                { 
                    implementedContracts.Add(GetConfigKey(contract), contract);
                } 
                return implementedContracts; 
            }
 
            internal static string GetConfigKey(ContractDescription contract)
            {
                return contract.ConfigurationName;
            } 
        }
 
        class ReflectedAndBehaviorContractCollection 
        {
            ReflectedContractCollection reflectedContracts; 
            KeyedByTypeCollection behaviors;
            public ReflectedAndBehaviorContractCollection(ReflectedContractCollection reflectedContracts, KeyedByTypeCollection behaviors)
            {
                this.reflectedContracts = reflectedContracts; 
                this.behaviors = behaviors;
            } 
 
            internal bool Contains(Type implementedContract)
            { 
                if (this.reflectedContracts.Contains(implementedContract))
                {
                    return true;
                } 

                if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract)) 
                { 
                    return true;
                } 

                return false;
            }
 
            internal string GetConfigKey(Type implementedContract)
            { 
                if (this.reflectedContracts.Contains(implementedContract)) 
                {
                    return ReflectedContractCollection.GetConfigKey(reflectedContracts[implementedContract]); 
                }

                if (this.behaviors.Contains(typeof(ServiceMetadataBehavior)) && ServiceMetadataBehavior.IsMetadataImplementedType(implementedContract))
                { 
                    return ServiceMetadataBehavior.MexContractName;
                } 
 
                DiagnosticUtility.DebugAssert("Calls to GetConfigKey are preceeded by calls to Contains.");
#pragma warning suppress 56506 // implementedContract is never null at this point 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SfxReflectedContractKeyNotFound2, implementedContract.FullName, string.Empty)));

            }
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

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