Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / ContractInferenceHelper.cs / 1407647 / ContractInferenceHelper.cs
//------------------------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //----------------------------------------------------------------------------- namespace System.ServiceModel.Activities { using System.Activities; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Net.Security; using System.Runtime; using System.ServiceModel.Activities.Description; using System.ServiceModel.Channels; using System.ServiceModel.Description; using System.Xml; using System.Xml.Linq; static class ContractInferenceHelper { static DataContractFormatAttribute dataContractFormatAttribute; static XmlSerializerFormatAttribute xmlSerializerFormatAttribute; static Type exceptionType; static Type faultExceptionType; public static DataContractFormatAttribute DataContractFormatAttribute { get { if (dataContractFormatAttribute == null) { dataContractFormatAttribute = new DataContractFormatAttribute(); } return dataContractFormatAttribute; } } public static XmlSerializerFormatAttribute XmlSerializerFormatAttribute { get { if (xmlSerializerFormatAttribute == null) { xmlSerializerFormatAttribute = new XmlSerializerFormatAttribute { SupportFaults = true }; } return xmlSerializerFormatAttribute; } } public static Type ExceptionType { get { if (exceptionType == null) { exceptionType = typeof(Exception); } return exceptionType; } } public static Type FaultExceptionType { get { if (faultExceptionType == null) { faultExceptionType = typeof(FaultException<>); } return faultExceptionType; } } public static void ProvideDefaultNamespace(ref XName serviceContractName) { Fx.Assert(serviceContractName != null, "Argument cannot be null!"); if (string.IsNullOrEmpty(serviceContractName.NamespaceName)) { // If no namespace is given by the user, we provide default namespace. This is consistent with WCF. serviceContractName = XName.Get(serviceContractName.LocalName, NamingHelper.DefaultNamespace); } } public static ContractDescription CreateContractFromOperation(XName serviceContractName, OperationDescription operation) { Fx.Assert(serviceContractName != null, "serviceContractName cannot be null"); ProvideDefaultNamespace(ref serviceContractName); ContractDescription contract = new ContractDescription(serviceContractName.LocalName, serviceContractName.NamespaceName) { // For inferred client side contracts, we do not set ContractType ConfigurationName = serviceContractName.LocalName, SessionMode = SessionMode.Allowed }; contract.Operations.Add(operation); return contract; } public static ContractDescription CreateOutputChannelContractDescription(XName serviceContractName, ProtectionLevel? protectionLevel) { Fx.Assert(serviceContractName != null, "cannot be null"); Type channelType = typeof(IOutputChannel); ProvideDefaultNamespace(ref serviceContractName); ContractDescription contract = new ContractDescription(serviceContractName.LocalName, serviceContractName.NamespaceName) { ContractType = channelType, ConfigurationName = serviceContractName.LocalName, SessionMode = SessionMode.Allowed }; OperationDescription operation = new OperationDescription("Send", contract); MessageDescription message = new MessageDescription(MessageHeaders.WildcardAction, MessageDirection.Input); operation.Messages.Add(message); if (protectionLevel.HasValue) { operation.ProtectionLevel = protectionLevel.Value; } contract.Operations.Add(operation); return contract; } public static ContractDescription CreateRequestChannelContractDescription(XName serviceContractName, ProtectionLevel? protectionLevel) { Fx.Assert(serviceContractName != null, "cannot be null"); Type channelType = typeof(IRequestChannel); ProvideDefaultNamespace(ref serviceContractName); ContractDescription contract = new ContractDescription(serviceContractName.LocalName, serviceContractName.NamespaceName) { ContractType = channelType, ConfigurationName = serviceContractName.LocalName, SessionMode = SessionMode.Allowed }; OperationDescription operation = new OperationDescription("Request", contract); MessageDescription request = new MessageDescription(MessageHeaders.WildcardAction, MessageDirection.Input); MessageDescription reply = new MessageDescription(MessageHeaders.WildcardAction, MessageDirection.Output); operation.Messages.Add(request); operation.Messages.Add(reply); if (protectionLevel.HasValue) { operation.ProtectionLevel = protectionLevel.Value; } contract.Operations.Add(operation); return contract; } public static void EnsureTransactionFlowOnContract( ref ServiceEndpoint serviceEndpoint, XName serviceContractName, string operationName, string action, ProtectionLevel? protectionLevel) { Fx.Assert(serviceEndpoint != null, "ServiceEndpoint cannot be null!"); // Client side fully inferred contract always has null ContractType if (serviceEndpoint.Contract.ContractType == null) { // If we are using the real contract, we only need to add TrancactionFlowAttribute to the operation Fx.Assert(serviceEndpoint.Contract.Operations.Count == 1, "Client side contract should have exactly one operation!"); serviceEndpoint.Contract.Operations[0].Behaviors.Add(new TransactionFlowAttribute(TransactionFlowOption.Allowed)); } else { // Replace the original fake contract with a fake contract tailored for transaction ContractDescription contract = null; OperationDescription operation = null; MessageDescription request = null; MessageDescription reply = null; Type channelType = typeof(IRequestChannel); // We need to create a contract description with the real service contract name // and operation name and actions and with the TransactionFlow operation behavior // because the TransactionChannelFactory has a dictionary of "Directional Action" to // transaction flow value that it uses to decide whether or not to include the // transaction header in the message. Fx.Assert(serviceContractName != null, "Argument serviceContractName cannot be null!"); Fx.Assert(operationName != null, "Argument operationName cannot be null!"); ProvideDefaultNamespace(ref serviceContractName); contract = new ContractDescription(serviceContractName.LocalName, serviceContractName.NamespaceName) { ContractType = channelType, SessionMode = SessionMode.Allowed }; operation = new OperationDescription(operationName, contract); operation.Behaviors.Add(new TransactionFlowAttribute(TransactionFlowOption.Allowed)); string requestAction = null; string replyAction = null; if (String.IsNullOrEmpty(action)) { // Construct the action. requestAction = NamingHelper.GetMessageAction(operation, false); replyAction = NamingHelper.GetMessageAction(operation, true); } else { requestAction = action; replyAction = action + TypeLoader.ResponseSuffix; } request = new MessageDescription(requestAction, MessageDirection.Input); reply = new MessageDescription(replyAction, MessageDirection.Output); operation.Messages.Add(request); operation.Messages.Add(reply); if (protectionLevel.HasValue) { operation.ProtectionLevel = protectionLevel.Value; } contract.Operations.Add(operation); // We need to replace the ServiceEndpoint because ServiceEndpoint.Contract does not have a public setter Uri listenUri = serviceEndpoint.ListenUri; serviceEndpoint = new ServiceEndpoint(contract) { Binding = serviceEndpoint.Binding, Address = serviceEndpoint.Address, Name = serviceEndpoint.Name, }; if (listenUri != null) { serviceEndpoint.ListenUri = listenUri; } } } public static OperationDescription CreateOneWayOperationDescription(Send send) { Fx.Assert(send != null, "Argument cannot be null!"); return CreateOperationDescriptionCore(send, null); } public static OperationDescription CreateTwoWayOperationDescription(Send send, ReceiveReply receiveReply) { Fx.Assert(send != null && receiveReply != null, "Arguments cannot be null!"); return CreateOperationDescriptionCore(send, receiveReply); } static OperationDescription CreateOperationDescriptionCore(Send send, ReceiveReply receiveReply) { XName contractXName = send.ServiceContractName; ProvideDefaultNamespace(ref contractXName); // Infer Name, Namespace, ConfigurationName ContractDescription contract = new ContractDescription(contractXName.LocalName, contractXName.NamespaceName); contract.ConfigurationName = send.EndpointConfigurationName; OperationDescription operation = new OperationDescription(NamingHelper.XmlName(send.OperationName), contract); if (send.ProtectionLevel.HasValue) { operation.ProtectionLevel = send.ProtectionLevel.Value; } AddKnownTypesToOperation(operation, send.KnownTypes); // Infer In-Message send.InternalContent.InferMessageDescription(operation, send, MessageDirection.Input); // Infer Out-Message if (receiveReply != null) { receiveReply.InternalContent.InferMessageDescription(operation, receiveReply, MessageDirection.Output); } PostProcessOperation(operation); AddSerializerProvider(operation, send.SerializerOption); contract.Operations.Add(operation); return operation; } // Create server side OperationDescription public static OperationDescription CreateOperationDescription(Receive receive, ContractDescription contract) { OperationDescription operation = new OperationDescription(NamingHelper.XmlName(receive.OperationName), contract); if (receive.ProtectionLevel.HasValue) { operation.ProtectionLevel = receive.ProtectionLevel.Value; } // Infer In-Message receive.InternalContent.InferMessageDescription(operation, receive, MessageDirection.Input); // Infer Out-Message if (receive.HasReply) { // At this point, we already know all the following SendReplies are equivalent SendReply sendReply = receive.FollowingReplies[0]; sendReply.InternalContent.InferMessageDescription(operation, sendReply, MessageDirection.Output); } else if (receive.HasFault) { // We infer Receive-SendFault pair as a two-way operation with void return value CheckForDisposableParameters(operation, Constants.EmptyTypeArray); AddOutputMessage(operation, null, Constants.EmptyStringArray, Constants.EmptyTypeArray); } PostProcessOperation(operation); // Behaviors AddSerializerProvider(operation, receive.SerializerOption); AddWorkflowOperationBehaviors(operation, receive.OperationBookmarkName, receive.CanCreateInstance); if (receive.InternalReceive.AdditionalData.IsInsideTransactedReceiveScope) { operation.IsInsideTransactedReceiveScope = true; EnableTransactionBehavior(operation); if (receive.InternalReceive.AdditionalData.IsFirstReceiveOfTransactedReceiveScopeTree) { operation.IsFirstReceiveOfTransactedReceiveScopeTree = true; } } return operation; } public static void AddInputMessage(OperationDescription operation, string overridingAction, Type type, SerializerOption serializerOption) { Fx.Assert(operation.Messages.Count == 0, "Operation already has input message"); bool isResponse = false; MessageDescription message = MessageBuilder.CreateMessageDescription( operation, isResponse, MessageDirection.Input, overridingAction, type, serializerOption); operation.Messages.Add(message); } public static void AddInputMessage(OperationDescription operation, string overridingAction, string[] argumentNames, Type[] argumentTypes) { Fx.Assert(operation.Messages.Count == 0, "Operation already has input message"); bool isResponse = false; MessageDescription message = MessageBuilder.CreateMessageDescription( operation, isResponse, MessageDirection.Input, overridingAction, argumentNames, argumentTypes); operation.Messages.Add(message); } public static void AddOutputMessage(OperationDescription operation, string overridingAction, Type type, SerializerOption serializerOption) { Fx.Assert(operation.Messages.Count > 0, "Operation does not have input message"); Fx.Assert(operation.Messages.Count < 2, "Operation already has output message"); bool isResponse = true; MessageDescription message = MessageBuilder.CreateMessageDescription( operation, isResponse, MessageDirection.Output, overridingAction, type, serializerOption); operation.Messages.Add(message); } public static void AddOutputMessage(OperationDescription operation, string overridingAction, string[] argumentNames, Type[] argumentTypes) { Fx.Assert(operation.Messages.Count > 0, "Operation does not have input message"); Fx.Assert(operation.Messages.Count < 2, "Operation already has output message"); bool isResponse = true; MessageDescription message = MessageBuilder.CreateMessageDescription( operation, isResponse, MessageDirection.Output, overridingAction, argumentNames, argumentTypes); operation.Messages.Add(message); } static void AddKnownTypesToOperation(OperationDescription operation, CollectionknownTypes) { if (knownTypes != null) { foreach (Type knownType in knownTypes) { operation.KnownTypes.Add(knownType); } } } public static void CheckForDisposableParameters(OperationDescription operation, Type type) { if (type == null) { operation.HasNoDisposableParameters = true; } else { operation.HasNoDisposableParameters = !ServiceReflector.IsParameterDisposable(type); } } public static void CheckForDisposableParameters(OperationDescription operation, Type[] types) { Fx.Assert(types != null, "Argument cannot be null!"); operation.HasNoDisposableParameters = true; foreach (Type type in types) { if (ServiceReflector.IsParameterDisposable(type)) { operation.HasNoDisposableParameters = false; break; } } } static void EnableTransactionBehavior(OperationDescription operationDescription) { Fx.Assert(operationDescription != null, "OperationDescription is null"); OperationBehaviorAttribute attribute = operationDescription.Behaviors.Find (); if (attribute != null) { attribute.TransactionScopeRequired = true; attribute.TransactionAutoComplete = false; } else { OperationBehaviorAttribute attr = new OperationBehaviorAttribute { TransactionAutoComplete = false, TransactionScopeRequired = true }; operationDescription.Behaviors.Add(attr); } TransactionFlowAttribute transactionFlowAttribute = operationDescription.Behaviors.Find (); if (transactionFlowAttribute != null) { if(transactionFlowAttribute.Transactions != TransactionFlowOption.Allowed) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.ContractInferenceValidationForTransactionFlowBehavior)); } } else { if (!operationDescription.IsOneWay) { operationDescription.Behaviors.Add(new TransactionFlowAttribute(TransactionFlowOption.Allowed)); } } } static void PostProcessOperation(OperationDescription operation) { MessageBuilder.ClearWrapperNames(operation); } static void AddSerializerProvider(OperationDescription operation, SerializerOption serializerOption) { switch (serializerOption) { case SerializerOption.DataContractSerializer: AddDataContractSerializerFormat(operation); break; case SerializerOption.XmlSerializer: AddXmlSerializerFormat(operation); break; } } static void AddDataContractSerializerFormat(OperationDescription operation) { if (operation.Behaviors.Find () != null) { throw FxTrace.Exception.AsError(new InvalidOperationException(SR.OperationHasSerializerBehavior( operation.Name, operation.DeclaringContract.Name, typeof(DataContractSerializerOperationBehavior)))); } operation.Behaviors.Add(new DataContractSerializerOperationBehavior(operation, DataContractFormatAttribute)); if (!operation.Behaviors.Contains(typeof(DataContractSerializerOperationGenerator))) { operation.Behaviors.Add(new DataContractSerializerOperationGenerator()); } } static void AddXmlSerializerFormat(OperationDescription operation) { if (operation.Behaviors.Find () != null) { throw FxTrace.Exception.AsError(new InvalidOperationException( SR.OperationHasSerializerBehavior(operation.Name, operation.DeclaringContract.Name, typeof(XmlSerializerOperationBehavior)))); } operation.Behaviors.Add(new XmlSerializerOperationBehavior(operation, XmlSerializerFormatAttribute)); if (!operation.Behaviors.Contains(typeof(XmlSerializerOperationGenerator))) { operation.Behaviors.Add(new XmlSerializerOperationGenerator(new XmlSerializerImportOptions())); } } static void AddWorkflowOperationBehaviors(OperationDescription operation, string bookmarkName, bool canCreateInstance) { KeyedByTypeCollection behaviors = operation.Behaviors; WorkflowOperationBehavior workflowOperationBehavior = behaviors.Find (); if (workflowOperationBehavior == null) { behaviors.Add(new WorkflowOperationBehavior(new Bookmark(bookmarkName), canCreateInstance)); } else { workflowOperationBehavior.CanCreateInstance = workflowOperationBehavior.CanCreateInstance || canCreateInstance; } } public static void CorrectOutMessageForOperation(Receive receive, OperationDescription operation) { // Remove the original outMessage Fx.Assert(operation.Messages.Count == 2, "OperationDescription must be two-way for CorrectOutMessageForOperation to be invoked!"); operation.Messages.RemoveAt(1); SendReply sendReply = receive.FollowingReplies[0]; sendReply.InternalContent.InferMessageDescription(operation, sendReply, MessageDirection.Output); ContractInferenceHelper.PostProcessOperation(operation); } public static void UpdateIsOneWayFlag(Receive receive, OperationDescription operation) { // Set InternalReceiveMessage.IsOneWay to false for two-way operations if (!operation.IsOneWay) { receive.SetIsOneWay(false); } } public static void AddFaultDescription(Receive activity, OperationDescription operation) { if (activity.HasFault) { foreach (SendReply sendFault in activity.FollowingFaults) { string action = null; Type type = null; action = sendFault.Action; SendMessageContent sendReply = sendFault.InternalContent as SendMessageContent; if (sendReply != null) { type = sendReply.InternalDeclaredMessageType; } else { SendParametersContent sendReplyParameters = sendFault.InternalContent as SendParametersContent; if (sendReplyParameters != null) { type = sendReplyParameters.ArgumentTypes[0]; // Exception should be the only parameter in SendFault } } Fx.Assert(type != null, "Exception type cannot be null!"); if (type.IsGenericType && type.GetGenericTypeDefinition() == FaultExceptionType) { Type faultType = type.GetGenericArguments()[0]; bool exists = false; // We expect the number of fault types to be small, so we use iterative comparison foreach (FaultDescription faultDescription in operation.Faults) { if (faultDescription.DetailType == faultType) { if (faultDescription.Action != action) { throw FxTrace.Exception.AsError(new ValidationException(SR.SendRepliesHaveSameFaultTypeDifferentAction)); } else { exists = true; break; } } } if (!exists) { FaultDescription faultDescription = MessageBuilder.CreateFaultDescription(operation, faultType, action); operation.Faults.Add(faultDescription); } } } } } public static void AddKnownTypesToOperation(Receive receive, OperationDescription operation) { Collection knownTypes = receive.InternalKnownTypes; if (knownTypes != null) { foreach (Type knownType in knownTypes) { // We expect the number of known types to be small, so we use iterative comparison if (!operation.KnownTypes.Contains(knownType)) { operation.KnownTypes.Add(knownType); } } } } public static void AddReceiveToFormatterBehavior(Receive receive, OperationDescription operation) { Fx.Assert(receive != null && operation != null, "Argument cannot be null!"); KeyedByTypeCollection behaviors = operation.Behaviors; WorkflowFormatterBehavior formatterBehavior = behaviors.Find (); if (formatterBehavior == null) { formatterBehavior = new WorkflowFormatterBehavior(); behaviors.Add(formatterBehavior); } formatterBehavior.Receives.Add(receive); } public static CorrelationQuery CreateServerCorrelationQuery(MessageQuerySet select, Collection correlationInitializers, OperationDescription operation, bool isResponse) { Fx.Assert(operation != null, "Argument cannot be null!"); CorrelationQuery correlationQuery = CreateCorrelationQueryCore(select, correlationInitializers); if (correlationQuery != null) { string action = !isResponse ? operation.Messages[0].Action : operation.Messages[1].Action; correlationQuery.Where = new CorrelationActionMessageFilter { Action = action }; } return correlationQuery; } // this method generates the correlationQuery for client side send and receiveReply public static Collection CreateClientCorrelationQueries(MessageQuerySet select, Collection correlationInitializers, string overridingAction, XName serviceContractName, string operationName, bool isResponse) { Fx.Assert(serviceContractName != null && operationName != null, "Argument cannot be null!"); Collection queryCollection = new Collection (); CorrelationQuery correlationQuery = CreateCorrelationQueryCore(select, correlationInitializers); if (correlationQuery != null) { if (overridingAction != null) { correlationQuery.Where = new CorrelationActionMessageFilter { Action = overridingAction }; } else { ProvideDefaultNamespace(ref serviceContractName); string defaultAction = NamingHelper.GetMessageAction(new XmlQualifiedName(serviceContractName.LocalName, serviceContractName.NamespaceName), operationName, null, isResponse); correlationQuery.Where = new CorrelationActionMessageFilter { Action = defaultAction }; } queryCollection.Add(correlationQuery); if (isResponse) { // we need an additional query with empty action to support soap1.1 reply cases CorrelationQuery noActionQuery = correlationQuery.Clone(); noActionQuery.Where = new CorrelationActionMessageFilter { Action = String.Empty }; queryCollection.Add(noActionQuery); } } return queryCollection; } static CorrelationQuery CreateCorrelationQueryCore(MessageQuerySet select, Collection correlationInitializers) { CorrelationQuery correlationQuery = null; if (select != null) { Fx.Assert(select.Count != 0, "Empty MessageQuerySet is not allowed!"); correlationQuery = new CorrelationQuery { Select = select }; } if (correlationInitializers != null && correlationInitializers.Count > 0) { foreach (CorrelationInitializer correlation in correlationInitializers) { QueryCorrelationInitializer queryCorrelation = correlation as QueryCorrelationInitializer; if (queryCorrelation != null) { Fx.Assert(queryCorrelation.MessageQuerySet.Count != 0, "Empty MessageQuerySet is not allowed!"); correlationQuery = correlationQuery ?? new CorrelationQuery(); correlationQuery.SelectAdditional.Add(queryCorrelation.MessageQuerySet); } } } return correlationQuery; } } } // File provided for Reference Use Only by Microsoft Corporation (c) 2007.
Link Menu
This book is available now!
Buy at Amazon US or
Buy at Amazon UK
- IPipelineRuntime.cs
- ReaderWriterLock.cs
- GiveFeedbackEvent.cs
- DetailsViewUpdatedEventArgs.cs
- LoginUtil.cs
- DoubleLinkListEnumerator.cs
- Guid.cs
- ReadOnlyState.cs
- ListViewSelectEventArgs.cs
- ProfileManager.cs
- DefaultTextStoreTextComposition.cs
- IDictionary.cs
- NavigatingCancelEventArgs.cs
- ManagementScope.cs
- ProcessThreadCollection.cs
- ListViewCancelEventArgs.cs
- ContainerUtilities.cs
- RectAnimationClockResource.cs
- DocumentViewerConstants.cs
- _Win32.cs
- NodeInfo.cs
- LinqDataSourceUpdateEventArgs.cs
- MdiWindowListItemConverter.cs
- Error.cs
- CodeAttachEventStatement.cs
- JavascriptCallbackResponseProperty.cs
- FixedFindEngine.cs
- QualifierSet.cs
- CallbackValidator.cs
- ConcurrentDictionary.cs
- BoundingRectTracker.cs
- HttpBindingExtension.cs
- XmlChildNodes.cs
- HtmlInputButton.cs
- HtmlElementEventArgs.cs
- ProxyFragment.cs
- MembershipValidatePasswordEventArgs.cs
- KeyValueInternalCollection.cs
- EventPropertyMap.cs
- TimeoutValidationAttribute.cs
- _TLSstream.cs
- DodSequenceMerge.cs
- IProducerConsumerCollection.cs
- DataServiceRequest.cs
- TypeConverterValueSerializer.cs
- HttpChannelBindingToken.cs
- OutputCacheModule.cs
- OuterGlowBitmapEffect.cs
- DataControlExtensions.cs
- ContractMapping.cs
- DynamicField.cs
- AsymmetricSignatureFormatter.cs
- UrlAuthFailedErrorFormatter.cs
- NotifyCollectionChangedEventArgs.cs
- SQLGuid.cs
- ColorContextHelper.cs
- ObjectStateEntryDbUpdatableDataRecord.cs
- WebSysDefaultValueAttribute.cs
- Table.cs
- WebExceptionStatus.cs
- BindingContext.cs
- AttributeData.cs
- DesignerActionPropertyItem.cs
- CompositeFontParser.cs
- FixedSOMGroup.cs
- KerberosSecurityTokenParameters.cs
- BuilderPropertyEntry.cs
- MethodToken.cs
- ConnectionPoint.cs
- HotSpotCollection.cs
- CompilerError.cs
- FileSystemInfo.cs
- CodeVariableDeclarationStatement.cs
- OdbcEnvironment.cs
- Label.cs
- TextCompositionManager.cs
- AttributeCollection.cs
- DataTrigger.cs
- PropertyEntry.cs
- AdornerDecorator.cs
- AppearanceEditorPart.cs
- ClaimTypeElement.cs
- StateWorkerRequest.cs
- InstanceDataCollection.cs
- XPathDocument.cs
- ScriptManagerProxy.cs
- Converter.cs
- TreeViewEvent.cs
- QueryCursorEventArgs.cs
- ConfigurationCollectionAttribute.cs
- WebPartAddingEventArgs.cs
- Roles.cs
- SimpleType.cs
- xsdvalidator.cs
- GridViewDeleteEventArgs.cs
- ActivityDesigner.cs
- NullRuntimeConfig.cs
- HttpWebRequestElement.cs
- Sql8ExpressionRewriter.cs
- DynamicResourceExtensionConverter.cs