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
- WebPartUserCapability.cs
- InputLangChangeEvent.cs
- DbUpdateCommandTree.cs
- BinaryQueryOperator.cs
- PersonalizationAdministration.cs
- ContextMenuStrip.cs
- DrawingGroup.cs
- TimeZone.cs
- KeyGestureValueSerializer.cs
- SqlTypesSchemaImporter.cs
- RowToParametersTransformer.cs
- JapaneseLunisolarCalendar.cs
- FormClosingEvent.cs
- Thread.cs
- BinaryEditor.cs
- CurrencyManager.cs
- MimeBasePart.cs
- WindowsGraphics.cs
- LassoHelper.cs
- RelativeSource.cs
- SafeLocalMemHandle.cs
- datacache.cs
- SizeLimitedCache.cs
- PrimitiveList.cs
- mediaeventargs.cs
- SmiEventStream.cs
- PeerNearMe.cs
- NullableLongAverageAggregationOperator.cs
- ExpressionVisitor.cs
- ScrollProviderWrapper.cs
- Rijndael.cs
- XpsSerializerWriter.cs
- DependencyObjectPropertyDescriptor.cs
- DocumentScope.cs
- GeneralTransform3D.cs
- Clipboard.cs
- SqlConnectionFactory.cs
- Site.cs
- Base64Encoder.cs
- ClientApiGenerator.cs
- ContractMapping.cs
- EntitySet.cs
- WebPartUtil.cs
- CopyAttributesAction.cs
- sqlpipe.cs
- PathSegmentCollection.cs
- RuleSetReference.cs
- RequestCacheEntry.cs
- XmlSerializationReader.cs
- UriSection.cs
- AxisAngleRotation3D.cs
- SqlTriggerContext.cs
- SuppressIldasmAttribute.cs
- RolePrincipal.cs
- UrlPath.cs
- ResourceWriter.cs
- XamlTypeMapper.cs
- DbProviderConfigurationHandler.cs
- HotCommands.cs
- SelectorAutomationPeer.cs
- EventSetter.cs
- GridViewRow.cs
- DecoratedNameAttribute.cs
- WebBrowserBase.cs
- _ContextAwareResult.cs
- ResourceExpressionBuilder.cs
- LineVisual.cs
- XmlTextWriter.cs
- TypeBrowser.xaml.cs
- SingleAnimation.cs
- GridViewSelectEventArgs.cs
- Camera.cs
- CompilerWrapper.cs
- SqlDataSourceCommandEventArgs.cs
- CorrelationManager.cs
- SiteMapNodeItem.cs
- BStrWrapper.cs
- IPGlobalProperties.cs
- SynchronizationFilter.cs
- mediaeventshelper.cs
- ListViewGroupConverter.cs
- CombinedGeometry.cs
- EntityCommand.cs
- FlowchartSizeFeature.cs
- SqlConnectionHelper.cs
- ButtonFlatAdapter.cs
- KeyValuePair.cs
- SessionPageStateSection.cs
- WmpBitmapDecoder.cs
- DocumentDesigner.cs
- DependencyPropertyConverter.cs
- StopStoryboard.cs
- RangeValidator.cs
- ResourceCategoryAttribute.cs
- PageAdapter.cs
- EncoderFallback.cs
- NamespaceListProperty.cs
- WorkflowFormatterBehavior.cs
- InheritanceContextChangedEventManager.cs
- ActivationServices.cs