Code:
/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Activities / System / ServiceModel / Activities / WorkflowService.cs / 1480445 / WorkflowService.cs
//----------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//---------------------------------------------------------------
namespace System.ServiceModel.Activities
{
using System.Activities;
using System.Activities.Debugger;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime;
using System.ServiceModel.Activities.Description;
using System.ServiceModel.Description;
using System.ServiceModel.XamlIntegration;
using System.Windows.Markup;
using System.Xml;
using System.Xml.Linq;
[ContentProperty("Body")]
public class WorkflowService : IDebuggableWorkflowTree
{
Collection endpoints;
IDictionary cachedInferredContracts;
IDictionary> correlationQueryByContract;
IList knownServiceActivities;
HashSet receiveAndReplyPairs;
ServiceDescription serviceDescription;
XName inferedServiceName;
public WorkflowService()
{
}
[DefaultValue(null)]
public Activity Body
{
get;
set;
}
[Fx.Tag.KnownXamlExternal]
[DefaultValue(null)]
[TypeConverter(typeof(ServiceXNameTypeConverter))]
public XName Name
{
get;
set;
}
[DefaultValue(null)]
public string ConfigurationName
{
get;
set;
}
[DefaultValue(false)]
public bool AllowBufferedReceive
{
get;
set;
}
public Collection Endpoints
{
get
{
if (this.endpoints == null)
{
this.endpoints = new Collection();
}
return this.endpoints;
}
}
internal XName InternalName
{
get
{
if (this.Name != null)
{
return this.Name;
}
else
{
if (this.inferedServiceName == null)
{
Fx.Assert(this.Body != null, "Body cannot be null!");
if (this.Body.DisplayName.Length == 0)
{
throw FxTrace.Exception.AsError(new InvalidOperationException(SR.MissingDisplayNameInRootActivity));
}
this.inferedServiceName = XName.Get(XmlConvert.EncodeLocalName(this.Body.DisplayName));
}
return this.inferedServiceName;
}
}
}
internal IDictionary> CorrelationQueries
{
get
{
Fx.Assert(this.cachedInferredContracts != null, "Must infer contract first!");
return this.correlationQueryByContract;
}
}
public Activity GetWorkflowRoot()
{
return this.Body;
}
internal ServiceDescription GetEmptyServiceDescription()
{
if (this.serviceDescription == null)
{
WalkActivityTree();
ServiceDescription result = new ServiceDescription
{
Name = this.InternalName.LocalName,
Namespace = string.IsNullOrEmpty(this.InternalName.NamespaceName) ? NamingHelper.DefaultNamespace : this.InternalName.NamespaceName,
ConfigurationName = this.ConfigurationName ?? this.InternalName.LocalName
};
result.Behaviors.Add(new WorkflowServiceBehavior(this.Body));
this.serviceDescription = result;
}
return this.serviceDescription;
}
internal IDictionary GetContractDescriptions()
{
if (this.cachedInferredContracts == null)
{
WalkActivityTree();
Fx.Assert(this.knownServiceActivities != null && this.receiveAndReplyPairs != null, "Failed to walk the activity tree!");
this.correlationQueryByContract = new Dictionary>();
// Contract inference
IDictionary inferredContracts = new Dictionary();
IDictionary keyedByNameOperationInfo =
new Dictionary();
foreach (Receive receive in this.knownServiceActivities)
{
XName contractXName = FixServiceContractName(receive.ServiceContractName);
ContractAndOperationNameTuple tuple = new ContractAndOperationNameTuple(contractXName, receive.OperationName);
OperationInfo operationInfo;
if (keyedByNameOperationInfo.TryGetValue(tuple, out operationInfo))
{
// All Receives with same ServiceContractName and OperationName need to be validated
ContractValidationHelper.ValidateReceiveWithReceive(receive, operationInfo.Receive);
}
else
{
// Note that activities in keyedByNameOperationInfo are keyed by
// ServiceContractName and OperationName tuple. So we won't run into the case where
// two opertions have the same OperationName.
ContractDescription contract;
if (!inferredContracts.TryGetValue(contractXName, out contract))
{
// Infer Name, Namespace
contract = new ContractDescription(contractXName.LocalName, contractXName.NamespaceName);
// We use ServiceContractName.LocalName to bind contract with config
contract.ConfigurationName = contractXName.LocalName;
// We do NOT infer ContractDescription.ProtectionLevel
inferredContracts.Add(contractXName, contract);
}
OperationDescription operation = ContractInferenceHelper.CreateOperationDescription(receive, contract);
contract.Operations.Add(operation);
operationInfo = new OperationInfo(receive, operation);
keyedByNameOperationInfo.Add(tuple, operationInfo);
}
CorrectOutMessageForOperationWithFault(receive, operationInfo);
ContractInferenceHelper.UpdateIsOneWayFlag(receive, operationInfo.OperationDescription);
// FaultTypes and KnownTypes need to be collected from all Receive activities
ContractInferenceHelper.AddFaultDescription(receive, operationInfo.OperationDescription);
ContractInferenceHelper.AddKnownTypesToOperation(receive, operationInfo.OperationDescription);
// WorkflowFormatterBehavior should have reference to all the Receive activities
ContractInferenceHelper.AddReceiveToFormatterBehavior(receive, operationInfo.OperationDescription);
Collection correlationQueries = null;
// Collect CorrelationQuery from Receive
if (receive.HasCorrelatesOn || receive.HasCorrelationInitializers)
{
MessageQuerySet select = receive.HasCorrelatesOn ? receive.CorrelatesOn : null;
CorrelationQuery correlationQuery = ContractInferenceHelper.CreateServerCorrelationQuery(select,
receive.CorrelationInitializers, operationInfo.OperationDescription, false);
CollectCorrelationQuery(ref correlationQueries, contractXName, correlationQuery);
}
// Find all known Receive-Reply pair in the activity tree. Remove them from this.receiveAndReplyPairs
// Also collect CorrelationQuery from following replies
if (receive.HasReply)
{
foreach (SendReply reply in receive.FollowingReplies)
{
ReceiveAndReplyTuple pair = new ReceiveAndReplyTuple(receive, reply);
this.receiveAndReplyPairs.Remove(pair);
CollectCorrelationQueryFromReply(ref correlationQueries, contractXName,
reply, operationInfo.OperationDescription);
reply.SetContractName(contractXName);
}
}
if (receive.HasFault)
{
foreach (Activity fault in receive.FollowingFaults)
{
ReceiveAndReplyTuple pair = new ReceiveAndReplyTuple(receive, fault);
this.receiveAndReplyPairs.Remove(pair);
CollectCorrelationQueryFromReply(ref correlationQueries, contractXName,
fault, operationInfo.OperationDescription);
}
}
}
// Check for Receive referenced by SendReply but no longer in the activity tree
if (this.receiveAndReplyPairs.Count != 0)
{
throw FxTrace.Exception.AsError(new ValidationException(SR.DanglingReceive));
}
// Print out tracing information
if (TD.InferredContractDescriptionIsEnabled())
{
foreach (ContractDescription contract in inferredContracts.Values)
{
TD.InferredContractDescription(contract.Name, contract.Namespace);
if (TD.InferredOperationDescriptionIsEnabled())
{
foreach (OperationDescription operation in contract.Operations)
{
TD.InferredOperationDescription(operation.Name, contract.Name, operation.IsOneWay.ToString());
}
}
}
}
this.cachedInferredContracts = inferredContracts;
}
return this.cachedInferredContracts;
}
void WalkActivityTree()
{
if (this.knownServiceActivities != null)
{
// We return if we have already walked the activity tree
return;
}
if (this.Body == null)
{
throw FxTrace.Exception.AsError(new ValidationException(SR.MissingBodyInWorkflowService));
}
// Validate the activity tree
WorkflowInspectionServices.CacheMetadata(this.Body);
this.knownServiceActivities = new List();
this.receiveAndReplyPairs = new HashSet();
// Now let us walk the tree here
Queue activities = new Queue();
// The root activity is never "in" a TransactedReceiveScope
activities.Enqueue(new QueueItem(this.Body, null, null));
while (activities.Count > 0)
{
QueueItem queueItem = activities.Dequeue();
Fx.Assert(queueItem != null, "Queue item cannot be null");
Activity activity = queueItem.Activity;
Fx.Assert(queueItem.Activity != null, "Queue item's Activity cannot be null");
TransactedReceiveScope transactedReceiveScope = queueItem.ParentTransactedReceiveScope;
TransactedReceiveScope rootTransactedReceiveScope = queueItem.RootTransactedReceiveScope;
if (activity is Receive) // First, let's see if this is a Receive activity
{
Receive receive = (Receive)activity;
if (rootTransactedReceiveScope != null)
{
receive.InternalReceive.AdditionalData.IsInsideTransactedReceiveScope = true;
Fx.Assert(transactedReceiveScope != null, "Internal error.. TransactedReceiveScope should be valid here");
if ((receive == transactedReceiveScope.Request) && (transactedReceiveScope == rootTransactedReceiveScope))
{
receive.InternalReceive.AdditionalData.IsFirstReceiveOfTransactedReceiveScopeTree = true;
}
}
this.knownServiceActivities.Add(receive);
}
else if (activity is SendReply) // Let's see if this is a SendReply
{
SendReply sendReply = (SendReply)activity;
Receive pairedReceive = sendReply.Request;
Fx.Assert(pairedReceive != null, "SendReply must point to a Receive!");
if (sendReply.InternalContent.IsFault)
{
pairedReceive.FollowingFaults.Add(sendReply);
}
else
{
if (pairedReceive.HasReply)
{
SendReply followingReply = pairedReceive.FollowingReplies[0];
ContractValidationHelper.ValidateSendReplyWithSendReply(followingReply, sendReply);
}
pairedReceive.FollowingReplies.Add(sendReply);
}
ReceiveAndReplyTuple tuple = new ReceiveAndReplyTuple(pairedReceive, sendReply);
this.receiveAndReplyPairs.Add(tuple);
}
// Enqueue child activities and delegates
if (activity is TransactedReceiveScope)
{
transactedReceiveScope = activity as TransactedReceiveScope;
if (rootTransactedReceiveScope == null)
{
rootTransactedReceiveScope = transactedReceiveScope;
}
}
foreach (Activity childActivity in WorkflowInspectionServices.GetActivities(activity))
{
QueueItem queueData = new QueueItem(childActivity, transactedReceiveScope, rootTransactedReceiveScope);
activities.Enqueue(queueData);
}
}
}
XName FixServiceContractName(XName serviceContractName)
{
// By default, we use WorkflowService.Name as ServiceContractName
XName contractXName = serviceContractName ?? this.InternalName;
ContractInferenceHelper.ProvideDefaultNamespace(ref contractXName);
return contractXName;
}
void CorrectOutMessageForOperationWithFault(Receive receive, OperationInfo operationInfo)
{
Fx.Assert(receive != null && operationInfo != null, "Argument cannot be null!");
Receive prevReceive = operationInfo.Receive;
if (receive != prevReceive && receive.HasReply &&
!prevReceive.HasReply && prevReceive.HasFault)
{
ContractInferenceHelper.CorrectOutMessageForOperation(receive, operationInfo.OperationDescription);
operationInfo.Receive = receive;
}
}
void CollectCorrelationQuery(ref Collection queries, XName serviceContractName, CorrelationQuery correlationQuery)
{
Fx.Assert(serviceContractName != null, "Argument cannot be null!");
if (correlationQuery == null)
{
return;
}
if (queries == null && !this.correlationQueryByContract.TryGetValue(serviceContractName, out queries))
{
queries = new Collection();
this.correlationQueryByContract.Add(serviceContractName, queries);
}
queries.Add(correlationQuery);
}
void CollectCorrelationQueryFromReply(ref Collection correlationQueries, XName serviceContractName,
Activity reply, OperationDescription operation)
{
SendReply sendReply = reply as SendReply;
if (sendReply != null)
{
CorrelationQuery correlationQuery = ContractInferenceHelper.CreateServerCorrelationQuery(
null, sendReply.CorrelationInitializers, operation, true);
CollectCorrelationQuery(ref correlationQueries, serviceContractName, correlationQuery);
}
}
internal void ResetServiceDescription()
{
this.serviceDescription = null;
this.cachedInferredContracts = null;
}
struct ContractAndOperationNameTuple
{
XName ServiceContractXName;
string OperationName;
public ContractAndOperationNameTuple(XName serviceContractXName, string operationName)
{
this.ServiceContractXName = serviceContractXName;
this.OperationName = operationName;
}
}
struct ReceiveAndReplyTuple
{
Receive Receive;
Activity Reply;
public ReceiveAndReplyTuple(Receive receive, Activity reply)
{
this.Receive = receive;
this.Reply = reply;
}
}
class OperationInfo
{
Receive receive;
OperationDescription operationDescription;
public OperationInfo(Receive receive, OperationDescription operationDescription)
{
this.receive = receive;
this.operationDescription = operationDescription;
}
public Receive Receive
{
get { return this.receive; }
set { this.receive = value; }
}
public OperationDescription OperationDescription
{
get { return this.operationDescription; }
}
}
class QueueItem
{
Activity activity;
TransactedReceiveScope parent;
TransactedReceiveScope rootTransactedReceiveScope;
public QueueItem(Activity element, TransactedReceiveScope parent, TransactedReceiveScope rootTransactedReceiveScope)
{
this.activity = element;
this.parent = parent;
this.rootTransactedReceiveScope = rootTransactedReceiveScope;
}
public Activity Activity
{
get { return this.activity; }
}
public TransactedReceiveScope ParentTransactedReceiveScope
{
get { return this.parent; }
}
public TransactedReceiveScope RootTransactedReceiveScope
{
get { return this.rootTransactedReceiveScope; }
}
}
}
}
// 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
- CollectionMarkupSerializer.cs
- CodeExporter.cs
- ServiceModelStringsVersion1.cs
- TableItemProviderWrapper.cs
- SchemaTableColumn.cs
- SymmetricAlgorithm.cs
- MarkerProperties.cs
- StatusBar.cs
- DecoderFallback.cs
- DateTimeSerializationSection.cs
- Storyboard.cs
- ObjectFactoryCodeDomTreeGenerator.cs
- InsufficientExecutionStackException.cs
- EmptyEnumerable.cs
- Int32Converter.cs
- TakeQueryOptionExpression.cs
- Message.cs
- CodeExporter.cs
- AlgoModule.cs
- XmlBindingWorker.cs
- BamlResourceDeserializer.cs
- CodeDirectiveCollection.cs
- HierarchicalDataSourceIDConverter.cs
- CustomPeerResolverService.cs
- InfoCardBaseException.cs
- CommandLineParser.cs
- CallbackValidator.cs
- BackgroundFormatInfo.cs
- ViewGenResults.cs
- ActivationServices.cs
- Journaling.cs
- RouteParameter.cs
- IncrementalReadDecoders.cs
- CubicEase.cs
- AuthorizationRule.cs
- RowParagraph.cs
- SiteMapHierarchicalDataSourceView.cs
- JsonReader.cs
- StaticExtensionConverter.cs
- ManipulationPivot.cs
- NativeRecognizer.cs
- StructuredProperty.cs
- TextBox.cs
- RIPEMD160.cs
- AnnotationComponentChooser.cs
- DeclarationUpdate.cs
- EntryWrittenEventArgs.cs
- DnsEndpointIdentity.cs
- _AuthenticationState.cs
- SHA1.cs
- ProxyGenerationError.cs
- XmlSchemaDocumentation.cs
- SR.cs
- SecurityPolicySection.cs
- VariantWrapper.cs
- Membership.cs
- ProviderCollection.cs
- X509RawDataKeyIdentifierClause.cs
- ErrorCodes.cs
- SpellerInterop.cs
- ConfigUtil.cs
- PassportAuthenticationModule.cs
- CheckBoxRenderer.cs
- hwndwrapper.cs
- HtmlTitle.cs
- KerberosTicketHashIdentifierClause.cs
- ProxyElement.cs
- AssociationTypeEmitter.cs
- FrugalMap.cs
- VirtualizedContainerService.cs
- SoapServerProtocol.cs
- HtmlValidatorAdapter.cs
- xamlnodes.cs
- MediaScriptCommandRoutedEventArgs.cs
- CompletedAsyncResult.cs
- SqlMethods.cs
- WorkflowApplicationUnhandledExceptionEventArgs.cs
- CharUnicodeInfo.cs
- BitmapEffectvisualstate.cs
- DiscoveryReferences.cs
- XsdDuration.cs
- RoutedPropertyChangedEventArgs.cs
- RubberbandSelector.cs
- LineBreakRecord.cs
- FixedSOMTextRun.cs
- ProcessThreadDesigner.cs
- RouteParameter.cs
- sortedlist.cs
- DesignerHierarchicalDataSourceView.cs
- PixelShader.cs
- NullableBoolConverter.cs
- StateItem.cs
- ObjectKeyFrameCollection.cs
- TextRangeEditTables.cs
- ServiceOperationInfoTypeConverter.cs
- Int32Animation.cs
- lengthconverter.cs
- DataSourceCache.cs
- SafeIUnknown.cs
- ClientTarget.cs