File: System\ServiceModel\Description\ServiceEndpoint.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
 
namespace System.ServiceModel.Description
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Globalization;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Dispatcher;
 
    [DebuggerDisplay("Address={address}")]
    [DebuggerDisplay("Name={name}")]
    public class ServiceEndpoint
    {
        EndpointAddress address;
        Binding binding;
        ContractDescription contract;
        Uri listenUri;
        ListenUriMode listenUriMode = ListenUriMode.Explicit;
        KeyedByTypeCollection<IEndpointBehavior> behaviors;
        string id;
        XmlName name;
        bool isEndpointFullyConfigured = false;
 
        public ServiceEndpoint(ContractDescription contract)
        {
            if (contract == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");
            this.contract = contract;
        }
 
        public ServiceEndpoint(ContractDescription contract, Binding binding, EndpointAddress address)
        {
            if (contract == null)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("contract");            
 
            this.contract = contract;
            this.binding = binding;
            this.address = address;
        }
 
        public EndpointAddress Address
        {
            get { return this.address; }
            set { this.address = value; }
        }
 
        public KeyedCollection<Type, IEndpointBehavior> EndpointBehaviors
        {
            get { return this.Behaviors; }
        }
 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public KeyedByTypeCollection<IEndpointBehavior> Behaviors
        {
            get
            {
                if (this.behaviors == null)
                {
                    this.behaviors = new KeyedByTypeCollection<IEndpointBehavior>();
                }
 
                return this.behaviors;
            }
        }
 
        public Binding Binding
        {
            get { return this.binding; }
            set { this.binding = value; }
        }
 
        public ContractDescription Contract
        {
            get { return this.contract; }
            set
            {
                if (value == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value");
                }
                this.contract = value;
            }
        }
 
        public bool IsSystemEndpoint
        {
            get;
            set;
        }
 
        public string Name
        {
            get
            {
                if (!XmlName.IsNullOrEmpty(name))
                {
                    return name.EncodedName;
                }
                else if (binding != null)
                {
                    // Microsoft: composing names have potential problem of generating name that looks like an encoded name, consider avoiding '_'
                    return String.Format(CultureInfo.InvariantCulture, "{0}_{1}", new XmlName(Binding.Name).EncodedName, Contract.Name);
                }
                else
                {
                    return Contract.Name;
                }
            }
            set
            {
                name = new XmlName(value, true /*isEncoded*/);
            }
        }
 
        public Uri ListenUri
        {
            get 
            {
                if (this.listenUri == null)
                {
                    if (this.address == null)
                    {
                        return null;
                    }
                    else
                    {
                        return this.address.Uri;
                    }
                }
                else
                {
                    return this.listenUri;
                }
            }
            set
            {
                if (value != null && !value.IsAbsoluteUri)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("value", SR.GetString(SR.UriMustBeAbsolute));
                }
                this.listenUri = value;
            }
        }
 
        public ListenUriMode ListenUriMode
        {
            get { return this.listenUriMode; }
            set
            {
                if (!ListenUriModeHelper.IsDefined(value))
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
                }
                this.listenUriMode = value;
            }
        }
 
        internal string Id
        {
            get 
            { 
                if (id == null)
                    id = Guid.NewGuid().ToString();
                return id; 
            }
        }
 
        internal Uri UnresolvedAddress
        {
            get;
            set;
        }
 
        internal Uri UnresolvedListenUri
        {
            get;
            set;
        }
 
        // This method ensures that the description object graph is structurally sound and that none
        // of the fundamental SFx framework assumptions have been violated.
        internal void EnsureInvariants()
        {
            if (Binding == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.AChannelServiceEndpointSBindingIsNull0)));
            }
            if (Contract == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.AChannelServiceEndpointSContractIsNull0)));
            }
            this.Contract.EnsureInvariants();
            this.Binding.EnsureInvariants(this.Contract.Name);
        }
 
        internal void ValidateForClient()
        {
            Validate(true, false);
        }
 
        internal void ValidateForService(bool runOperationValidators)
        {
            Validate(runOperationValidators, true);
        }
 
        internal bool IsFullyConfigured 
        {
            get { return this.isEndpointFullyConfigured; }
            set { this.isEndpointFullyConfigured = value; }
        }
 
        // for V1 legacy reasons, a mex endpoint is considered a system endpoint even if IsSystemEndpoint = false
        internal bool InternalIsSystemEndpoint(ServiceDescription description)
        {
            if (ServiceMetadataBehavior.IsMetadataEndpoint(description, this))
            {
                return true;
            }
            return this.IsSystemEndpoint;
        }
 
        // This method runs validators (both builtin and ones in description).  
        // Precondition: EnsureInvariants() should already have been called.
        void Validate(bool runOperationValidators, bool isForService)
        {
            // contract behaviors
            ContractDescription contract = this.Contract;
            for (int j = 0; j < contract.Behaviors.Count; j++)
            {
                IContractBehavior iContractBehavior = contract.Behaviors[j];
                iContractBehavior.Validate(contract, this);
            }
            // endpoint behaviors
            if (!isForService)
            {
                (PartialTrustValidationBehavior.Instance as IEndpointBehavior).Validate(this);
#pragma warning disable 0618
                (PeerValidationBehavior.Instance as IEndpointBehavior).Validate(this);
#pragma warning restore 0618
                (TransactionValidationBehavior.Instance as IEndpointBehavior).Validate(this);
                (SecurityValidationBehavior.Instance as IEndpointBehavior).Validate(this);
                (System.ServiceModel.MsmqIntegration.MsmqIntegrationValidationBehavior.Instance as IEndpointBehavior).Validate(this);
            }
            for (int j = 0; j < this.Behaviors.Count; j++)
            {
                IEndpointBehavior ieb = this.Behaviors[j];
                ieb.Validate(this);
            }
            // operation behaviors
            if (runOperationValidators)
            {
                for (int j = 0; j < contract.Operations.Count; j++)
                {
                    OperationDescription op = contract.Operations[j];
                    TaskOperationDescriptionValidator.Validate(op, isForService);
                    for (int k = 0; k < op.Behaviors.Count; k++)
                    {
                        IOperationBehavior iob = op.Behaviors[k];
                        iob.Validate(op);
                    }
                }
            }
        }
    }
}