You've already forked linux-packaging-mono
							
							
		
			
	
	
		
			264 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			264 lines
		
	
	
		
			11 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|   | //----------------------------------------------------------------------------- | |||
|  | // Copyright (c) Microsoft Corporation.  All rights reserved. | |||
|  | //----------------------------------------------------------------------------- | |||
|  | 
 | |||
|  | namespace System.ServiceModel.Activities | |||
|  | { | |||
|  |     using System.Activities; | |||
|  |     using System.Activities.Statements; | |||
|  |     using System.Collections.ObjectModel; | |||
|  |     using System.ComponentModel; | |||
|  |     using System.ServiceModel.Channels; | |||
|  |     using System.ServiceModel.Description; | |||
|  |     using System.ServiceModel.Dispatcher; | |||
|  |     using System.Windows.Markup; | |||
|  | 
 | |||
|  |     // Used to receive the reply in a request/reply messaging pattern. Must be paired with | |||
|  |     // a corresponding Send activity. | |||
|  |     [ContentProperty("Content")] | |||
|  |     public sealed class ReceiveReply : Activity | |||
|  |     { | |||
|  |         Collection<CorrelationInitializer> correlationInitializers; | |||
|  |         FromReply responseFormatter; | |||
|  |         InternalReceiveMessage internalReceive; | |||
|  | 
 | |||
|  |         public ReceiveReply() | |||
|  |             : base() | |||
|  |         { | |||
|  |             base.Implementation = () => | |||
|  |             { | |||
|  |                 // if CacheMetadata isn't called, bail early | |||
|  |                 if (this.internalReceive == null) | |||
|  |                 { | |||
|  |                     return null; | |||
|  |                 } | |||
|  | 
 | |||
|  |                 // requestFormatter is null if we have an untyped message situation | |||
|  |                 if (this.responseFormatter == null)  | |||
|  |                 { | |||
|  |                     return this.internalReceive; | |||
|  |                 } | |||
|  |                 else | |||
|  |                 { | |||
|  |                     Variable<Message> response = new Variable<Message> { Name = "ResponseMessage" }; | |||
|  |                     this.internalReceive.Message = new OutArgument<Message>(response); | |||
|  |                     this.responseFormatter.Message = new InArgument<Message>(response); | |||
|  | 
 | |||
|  |                     return new MessagingNoPersistScope | |||
|  |                     { | |||
|  |                         Body = new Sequence | |||
|  |                         { | |||
|  |                             Variables = { response }, | |||
|  |                             Activities = | |||
|  |                                 { | |||
|  |                                     this.internalReceive, | |||
|  |                                     this.responseFormatter, | |||
|  |                                 } | |||
|  |                         } | |||
|  |                     }; | |||
|  |                 } | |||
|  |             }; | |||
|  |         } | |||
|  | 
 | |||
|  |         // the content to receive (either message or parameters-based) declared by the user | |||
|  |         [DefaultValue(null)] | |||
|  |         public ReceiveContent Content | |||
|  |         { | |||
|  |             get; | |||
|  |             set; | |||
|  |         } | |||
|  | 
 | |||
|  |         // Internally, we should always use InternalContent since this property may have default content that we added | |||
|  |         internal ReceiveContent InternalContent | |||
|  |         { | |||
|  |             get | |||
|  |             { | |||
|  |                 return this.Content ?? ReceiveContent.DefaultReceiveContent; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         [DefaultValue(null)] | |||
|  |         public string Action | |||
|  |         { | |||
|  |             get; | |||
|  |             set; | |||
|  |         } | |||
|  | 
 | |||
|  |         // Reference to the Send activity that is responsible for sending the Request part of the | |||
|  |         // request/reply pattern. This cannot be null. | |||
|  |         [DefaultValue(null)] | |||
|  |         public Send Request | |||
|  |         { | |||
|  |             get; | |||
|  |             set; | |||
|  |         } | |||
|  | 
 | |||
|  |         // Additional correlations allow situations where a "session" involves multiple | |||
|  |         // messages between two workflow instances. | |||
|  |         public Collection<CorrelationInitializer> CorrelationInitializers | |||
|  |         { | |||
|  |             get | |||
|  |             { | |||
|  |                 if (this.correlationInitializers == null) | |||
|  |                 { | |||
|  |                     this.correlationInitializers = new Collection<CorrelationInitializer>(); | |||
|  |                 } | |||
|  |                 return this.correlationInitializers; | |||
|  |             } | |||
|  |         } | |||
|  | 
 | |||
|  |         protected override void CacheMetadata(ActivityMetadata metadata) | |||
|  |         { | |||
|  |             if (this.Request == null) | |||
|  |             { | |||
|  |                 metadata.AddValidationError(SR.ReceiveReplyRequestCannotBeNull(this.DisplayName)); | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 // Need to validate Send.ServiceContractName and Send.OperationName here so that we can proceed with contract inference | |||
|  |                 if (this.Request.ServiceContractName == null) | |||
|  |                 { | |||
|  |                     string errorOperationName = ContractValidationHelper.GetErrorMessageOperationName(this.Request.OperationName); | |||
|  |                     metadata.AddValidationError(SR.MissingServiceContractName(this.Request.DisplayName, errorOperationName)); | |||
|  |                 } | |||
|  |                 if (string.IsNullOrEmpty(this.Request.OperationName)) | |||
|  |                 { | |||
|  |                     metadata.AddValidationError(SR.MissingOperationName(this.Request.DisplayName)); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             // validate Correlation Initializers | |||
|  |             MessagingActivityHelper.ValidateCorrelationInitializer(metadata, this.correlationInitializers, true, this.DisplayName, (this.Request != null ? this.Request.OperationName : String.Empty)); | |||
|  |              | |||
|  |             // Validate Content | |||
|  |             string operationName = this.Request != null ? this.Request.OperationName : null; | |||
|  |             this.InternalContent.CacheMetadata(metadata, this, operationName); | |||
|  | 
 | |||
|  |             if (this.correlationInitializers != null) | |||
|  |             { | |||
|  |                 for (int i = 0; i < this.correlationInitializers.Count; i++) | |||
|  |                 { | |||
|  |                     CorrelationInitializer initializer = this.correlationInitializers[i]; | |||
|  |                     initializer.ArgumentName = Constants.Parameter + i; | |||
|  |                     RuntimeArgument initializerArgument = new RuntimeArgument(initializer.ArgumentName, Constants.CorrelationHandleType, ArgumentDirection.In); | |||
|  |                     metadata.Bind(initializer.CorrelationHandle, initializerArgument); | |||
|  |                     metadata.AddArgument(initializerArgument); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             if (!metadata.HasViolations) | |||
|  |             { | |||
|  |                 this.internalReceive = CreateInternalReceive(); | |||
|  | 
 | |||
|  |                 InArgument<CorrelationHandle> requestReplyHandleFromSend = GetReplyHandleFromSend(); | |||
|  |                 if (requestReplyHandleFromSend != null) | |||
|  |                 { | |||
|  |                     InArgument<CorrelationHandle> resultCorrelatesWith = MessagingActivityHelper.CreateReplyCorrelatesWith(requestReplyHandleFromSend); | |||
|  | 
 | |||
|  |                     RuntimeArgument resultCorrelatesWithArgument = new RuntimeArgument("ResultCorrelatesWith", Constants.CorrelationHandleType, ArgumentDirection.In); | |||
|  |                     metadata.Bind(resultCorrelatesWith, resultCorrelatesWithArgument); | |||
|  |                     metadata.AddArgument(resultCorrelatesWithArgument); | |||
|  | 
 | |||
|  |                     this.internalReceive.CorrelatesWith = (InArgument<CorrelationHandle>)InArgument.CreateReference(resultCorrelatesWith, "ResultCorrelatesWith"); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 this.InternalContent.ConfigureInternalReceiveReply(this.internalReceive, out this.responseFormatter); | |||
|  | 
 | |||
|  |                 if (this.InternalContent is ReceiveMessageContent | |||
|  |                     && MessageBuilder.IsMessageContract(((ReceiveMessageContent)this.InternalContent).InternalDeclaredMessageType)) | |||
|  |                 { | |||
|  |                     this.Request.OperationUsesMessageContract = true; | |||
|  |                 } | |||
|  | 
 | |||
|  |                 OperationDescription operation = ContractInferenceHelper.CreateTwoWayOperationDescription(this.Request, this); | |||
|  |                 this.Request.OperationDescription = operation; | |||
|  | 
 | |||
|  |                 if (this.responseFormatter != null) | |||
|  |                 { | |||
|  |                     IClientMessageFormatter formatter = ClientOperationFormatterProvider.GetFormatterFromRuntime(operation); | |||
|  | 
 | |||
|  |                     this.Request.SetFormatter(formatter); | |||
|  |                     this.responseFormatter.Formatter = formatter; | |||
|  | 
 | |||
|  |                     //  | |||
|  |                     int index = 0; | |||
|  |                     Type[] faultTypes = new Type[operation.KnownTypes.Count]; | |||
|  |                     foreach (Type type in operation.KnownTypes) | |||
|  |                     { | |||
|  |                         faultTypes[index] = type; | |||
|  |                         index++; | |||
|  |                     } | |||
|  | 
 | |||
|  |                     this.responseFormatter.FaultFormatter = new FaultFormatter(faultTypes); | |||
|  |                 } | |||
|  | 
 | |||
|  |                 // Add CorrelationQuery to the Send->ReplyCorrelation, we validate that the same query is not added multiple times | |||
|  |                 if (this.correlationInitializers != null && this.correlationInitializers.Count > 0) | |||
|  |                 { | |||
|  |                     Collection<CorrelationQuery> internalCorrelationQueryCollection = ContractInferenceHelper.CreateClientCorrelationQueries(null, this.correlationInitializers, | |||
|  |                         this.Action, this.Request.ServiceContractName, this.Request.OperationName, true); | |||
|  | 
 | |||
|  |                     foreach (CorrelationQuery query in internalCorrelationQueryCollection) | |||
|  |                     { | |||
|  |                         this.Request.SetReplyCorrelationQuery(query); | |||
|  |                     } | |||
|  |                      | |||
|  |                 } | |||
|  |             } | |||
|  |             else | |||
|  |             { | |||
|  |                 this.internalReceive = null; | |||
|  |                 this.responseFormatter = null; | |||
|  |             } | |||
|  | 
 | |||
|  |             // We don't have any imported children despite referencing the Request | |||
|  |             metadata.SetImportedChildrenCollection(new Collection<Activity>()); | |||
|  |         } | |||
|  | 
 | |||
|  |         InternalReceiveMessage CreateInternalReceive() | |||
|  |         { | |||
|  |             InternalReceiveMessage result = new InternalReceiveMessage | |||
|  |             { | |||
|  |                 IsOneWay = false, | |||
|  |                 IsReceiveReply = true, | |||
|  |                 OwnerDisplayName = this.DisplayName | |||
|  |             }; | |||
|  | 
 | |||
|  |             if (this.correlationInitializers != null) | |||
|  |             { | |||
|  |                 foreach (CorrelationInitializer correlation in this.correlationInitializers) | |||
|  |                 { | |||
|  |                     result.CorrelationInitializers.Add(correlation.Clone()); | |||
|  |                 } | |||
|  |             } | |||
|  | 
 | |||
|  |             // Update the send->IsOneWay | |||
|  |             if (this.Request != null) | |||
|  |             { | |||
|  |                 this.Request.SetIsOneWay(false); | |||
|  |             } | |||
|  | 
 | |||
|  |             return result; | |||
|  |         } | |||
|  | 
 | |||
|  |         InArgument<CorrelationHandle> GetReplyHandleFromSend() | |||
|  |         { | |||
|  |             if (this.Request != null) | |||
|  |             { | |||
|  |                 // If user has set AdditionalCorrelations, then we need to first look for requestReply Handle there | |||
|  |                 foreach (CorrelationInitializer correlation in this.Request.CorrelationInitializers) | |||
|  |                 { | |||
|  |                     RequestReplyCorrelationInitializer requestReplyCorrelation = correlation as RequestReplyCorrelationInitializer; | |||
|  | 
 | |||
|  |                     if (requestReplyCorrelation != null && requestReplyCorrelation.CorrelationHandle != null) | |||
|  |                     { | |||
|  |                         return requestReplyCorrelation.CorrelationHandle; | |||
|  |                     } | |||
|  |                 } | |||
|  |             } | |||
|  |              | |||
|  |             return null; | |||
|  |         } | |||
|  |     } | |||
|  | } |