//---------------------------------------------------------------- // Copyright (c) Microsoft Corporation. All rights reserved. //---------------------------------------------------------------- namespace System.ServiceModel.Activities.Description { using System.Collections.ObjectModel; using System.Runtime; using System.ServiceModel.Activities.Dispatcher; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.ServiceModel.Dispatcher; using System.Xml; using SR = System.ServiceModel.Activities.SR; public sealed class BufferedReceiveServiceBehavior : IServiceBehavior { internal const int DefaultMaxPendingMessagesPerChannel = 512; int maxPendingMessagesPerChannel = DefaultMaxPendingMessagesPerChannel; public int MaxPendingMessagesPerChannel { get { return this.maxPendingMessagesPerChannel; } set { if (value <= 0) { throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.MaxPendingMessagesPerChannelMustBeGreaterThanZero); } this.maxPendingMessagesPerChannel = value; } } public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { if (serviceHostBase is WorkflowServiceHost) { foreach (ChannelDispatcherBase channelDispatcherBase in serviceHostBase.ChannelDispatchers) { ChannelDispatcher channelDispatcher = channelDispatcherBase as ChannelDispatcher; if (channelDispatcher != null) { foreach (EndpointDispatcher endpointDispatcher in channelDispatcher.Endpoints) { if (WorkflowServiceBehavior.IsWorkflowEndpoint(endpointDispatcher)) { // We need all incoming messages to be copyable endpointDispatcher.DispatchRuntime.PreserveMessage = true; // Enable BufferedReceive processing for each operation foreach (DispatchOperation dispatchOperation in endpointDispatcher.DispatchRuntime.Operations) { dispatchOperation.BufferedReceiveEnabled = true; } } } } } serviceHostBase.Extensions.Add(new BufferedReceiveManager(this.MaxPendingMessagesPerChannel)); } } public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { // Validate that ReceiveContext.ManualControl is set for each operation foreach (ServiceEndpoint serviceEndpoint in serviceDescription.Endpoints) { if (BufferedReceiveServiceBehavior.IsWorkflowEndpoint(serviceEndpoint)) { foreach (OperationDescription operation in serviceEndpoint.Contract.Operations) { ReceiveContextEnabledAttribute receiveContextEnabled = operation.Behaviors.Find(); if (receiveContextEnabled == null || !receiveContextEnabled.ManualControl) { throw FxTrace.Exception.AsError( new InvalidOperationException(SR.BufferedReceiveRequiresReceiveContext(operation.Name))); } } } } } public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection endpoints, BindingParameterCollection bindingParameters) { } // See WorkflowServiceBehavior.cs for another implementation of IsWorkflowEndpoint which // operates against EndpointDispatchers instead of ServiceEndpoints internal static bool IsWorkflowEndpoint(ServiceEndpoint serviceEndpoint) { if (serviceEndpoint.IsSystemEndpoint) { return false; } foreach (OperationDescription operation in serviceEndpoint.Contract.Operations) { if (operation.Behaviors.Find() == null) { return false; } } return true; } } }