File: FrameworkFork\System.ServiceModel\System\ServiceModel\Description\OperationDescription.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Diagnostics;
using System.Net.Security;
using System.Reflection;
 
namespace System.ServiceModel.Description
{
    [DebuggerDisplay("Name={name}, IsInitiating={isInitiating}, IsTerminating={isTerminating}")]
    public class OperationDescription
    {
        internal const string SessionOpenedAction = Channels.WebSocketTransportSettings.ConnectionOpenedAction;
 
        private XmlName _name;
        private bool _isInitiating;
        private bool _isTerminating;
        private bool _isSessionOpenNotificationEnabled;
        private ContractDescription _declaringContract;
        private FaultDescriptionCollection _faults;
        private MessageDescriptionCollection _messages;
        private KeyedByTypeCollection<IOperationBehavior> _behaviors;
        private Collection<Type> _knownTypes;
        private MethodInfo _beginMethod;
        private MethodInfo _endMethod;
        private MethodInfo _syncMethod;
        private MethodInfo _taskMethod;
        private ProtectionLevel _protectionLevel;
        private bool _hasProtectionLevel;
        private bool _validateRpcWrapperName = true;
        private bool _hasNoDisposableParameters;
 
        public OperationDescription(string name, ContractDescription declaringContract)
        {
            if (name == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("name");
            }
            if (name.Length == 0)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new ArgumentOutOfRangeException("name", SRServiceModel.SFxOperationDescriptionNameCannotBeEmpty));
            }
            _name = new XmlName(name, true /*isEncoded*/);
            if (declaringContract == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("declaringContract");
            }
            _declaringContract = declaringContract;
            _isInitiating = true;
            _isTerminating = true;
            _faults = new FaultDescriptionCollection();
            _messages = new MessageDescriptionCollection();
            _behaviors = new KeyedByTypeCollection<IOperationBehavior>();
            _knownTypes = new Collection<Type>();
        }
 
        internal OperationDescription(string name, ContractDescription declaringContract, bool validateRpcWrapperName)
            : this(name, declaringContract)
        {
            _validateRpcWrapperName = validateRpcWrapperName;
        }
 
        public KeyedCollection<Type, IOperationBehavior> OperationBehaviors
        {
            get { return this.Behaviors; }
        }
 
        [EditorBrowsable(EditorBrowsableState.Never)]
        public KeyedByTypeCollection<IOperationBehavior> Behaviors
        {
            get { return _behaviors; }
        }
 
        public ProtectionLevel ProtectionLevel
        {
            get { return _protectionLevel; }
            set
            {
                if (!(value == ProtectionLevel.None || value == ProtectionLevel.Sign || value == ProtectionLevel.EncryptAndSign))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value"));
                _protectionLevel = value;
                _hasProtectionLevel = true;
            }
        }
 
        public bool HasProtectionLevel
        {
            get { return _hasProtectionLevel; }
        }
 
 
        // Not serializable on purpose, metadata import/export cannot
        // produce it, only available when binding to runtime
        public MethodInfo TaskMethod
        {
            get { return _taskMethod; }
            set { _taskMethod = value; }
        }
 
        // Not serializable on purpose, metadata import/export cannot
        // produce it, only available when binding to runtime
        public MethodInfo SyncMethod
        {
            get { return _syncMethod; }
            set { _syncMethod = value; }
        }
 
        // Not serializable on purpose, metadata import/export cannot
        // produce it, only available when binding to runtime
        public MethodInfo BeginMethod
        {
            get { return _beginMethod; }
            set { _beginMethod = value; }
        }
 
        internal MethodInfo OperationMethod
        {
            get
            {
                if (this.SyncMethod == null)
                {
                    return this.TaskMethod ?? this.BeginMethod;
                }
                else
                {
                    return this.SyncMethod;
                }
            }
        }
 
 
        internal bool HasNoDisposableParameters
        {
            get { return _hasNoDisposableParameters; }
            set { _hasNoDisposableParameters = value; }
        }
 
        // Not serializable on purpose, metadata import/export cannot
        // produce it, only available when binding to runtime
        public MethodInfo EndMethod
        {
            get { return _endMethod; }
            set { _endMethod = value; }
        }
 
        public ContractDescription DeclaringContract
        {
            get { return _declaringContract; }
            set
            {
                if (value == null)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("DeclaringContract");
                }
                else
                {
                    _declaringContract = value;
                }
            }
        }
 
        public FaultDescriptionCollection Faults
        {
            get { return _faults; }
        }
 
        public bool IsOneWay
        {
            get { return this.Messages.Count == 1; }
        }
 
        public bool IsInitiating
        {
            get { return _isInitiating; }
            set { _isInitiating = value; }
        }
 
        internal bool IsServerInitiated()
        {
            EnsureInvariants();
            return Messages[0].Direction == MessageDirection.Output;
        }
 
        public bool IsTerminating
        {
            get { return _isTerminating; }
            set { _isTerminating = value; }
        }
 
        public Collection<Type> KnownTypes
        {
            get { return _knownTypes; }
        }
 
        // Messages[0] is the 'request' (first of MEP), and for non-oneway MEPs, Messages[1] is the 'response' (second of MEP)
        public MessageDescriptionCollection Messages
        {
            get { return _messages; }
        }
 
        internal XmlName XmlName
        {
            get { return _name; }
        }
 
        internal string CodeName
        {
            get { return _name.DecodedName; }
        }
 
        public string Name
        {
            get { return _name.EncodedName; }
        }
 
        internal bool IsValidateRpcWrapperName { get { return _validateRpcWrapperName; } }
 
        internal Type TaskTResult
        {
            get;
            set;
        }
 
        internal bool HasOutputParameters
        {
            get
            {
                // For non-oneway operations, Messages[1] is the 'response'
                return (this.Messages.Count > 1) &&
                    (this.Messages[1].Body.Parts.Count > 0);
            }
        }
 
        internal bool IsSessionOpenNotificationEnabled
        {
            get { return _isSessionOpenNotificationEnabled; }
            set { _isSessionOpenNotificationEnabled = value; }
        }
 
        internal void EnsureInvariants()
        {
            if (this.Messages.Count != 1 && this.Messages.Count != 2)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new System.InvalidOperationException(string.Format(SRServiceModel.SFxOperationMustHaveOneOrTwoMessages, this.Name)));
            }
        }
 
        internal void ResetProtectionLevel()
        {
            _protectionLevel = ProtectionLevel.None;
            _hasProtectionLevel = false;
        }
    }
}