#pragma warning disable 1634, 1691 namespace System.Workflow.ComponentModel { #region Imports using System; using System.Diagnostics; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Workflow.ComponentModel.Design; using System.Runtime.Serialization; using System.IO; using System.Runtime.Serialization.Formatters.Binary; using System.Workflow.ComponentModel.Serialization; #endregion [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] public sealed class ActivityExecutionContextManager { #region Data members and constructor private ActivityExecutionContext ownerContext = null; private List executionContexts = new List(); internal ActivityExecutionContextManager(ActivityExecutionContext ownerContext) { this.ownerContext = ownerContext; // Populate the child collection. IList activeContexts = (IList)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); if (activeContexts != null) { foreach (Activity activeContextActivity in activeContexts) this.executionContexts.Add(new ActivityExecutionContext(activeContextActivity)); } } #endregion #region Public members public ReadOnlyCollection ExecutionContexts { get { if (this.ownerContext == null) #pragma warning suppress 56503 throw new ObjectDisposedException("ActivityExecutionContextManager"); return new ReadOnlyCollection(this.executionContexts); } } public ActivityExecutionContext CreateExecutionContext(Activity activity) { if (this.ownerContext == null) throw new ObjectDisposedException("ActivityExecutionContextManager"); if (activity == null) throw new ArgumentNullException("activity"); if (!this.ownerContext.IsValidChild(activity, true)) throw new ArgumentException(SR.GetString(SR.AEC_InvalidActivity), "activity"); Activity copiedActivity = activity.Clone(); ((IDependencyObjectAccessor)copiedActivity).InitializeInstanceForRuntime(this.ownerContext.Activity.WorkflowCoreRuntime); //Reset the cloned tree for execution. Queue activityQueue = new Queue(); activityQueue.Enqueue(copiedActivity); while (activityQueue.Count != 0) { Activity clonedActivity = activityQueue.Dequeue(); if (clonedActivity.ExecutionStatus != ActivityExecutionStatus.Initialized) { clonedActivity.ResetAllKnownDependencyProperties(); CompositeActivity compositeActivity = clonedActivity as CompositeActivity; if (compositeActivity != null) { for (int i = 0; i < compositeActivity.EnabledActivities.Count; ++i) { activityQueue.Enqueue(compositeActivity.EnabledActivities[i]); } ISupportAlternateFlow alternateFlow = compositeActivity as ISupportAlternateFlow; if (alternateFlow != null) { for (int i = 0; i < alternateFlow.AlternateFlowActivities.Count; ++i) { activityQueue.Enqueue(alternateFlow.AlternateFlowActivities[i]); } } } } } // get active context activities and add it to this one IList activeContexts = (IList)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); if (activeContexts == null) { activeContexts = new List(); this.ownerContext.Activity.ContextActivity.SetValue(Activity.ActiveExecutionContextsProperty, activeContexts); } activeContexts.Add(copiedActivity); // prepare the copied activity as a context activity ActivityExecutionContextInfo contextInfo = new ActivityExecutionContextInfo(activity.QualifiedName, this.ownerContext.WorkflowCoreRuntime.GetNewContextActivityId(), Guid.NewGuid(), this.ownerContext.ContextId); copiedActivity.SetValue(Activity.ActivityExecutionContextInfoProperty, contextInfo); copiedActivity.SetValue(Activity.ActivityContextGuidProperty, contextInfo.ContextGuid); ActivityExecutionContext newExecutionContext = null; try { // inform workflow runtime this.ownerContext.Activity.WorkflowCoreRuntime.RegisterContextActivity(copiedActivity); // return the new context newExecutionContext = new ActivityExecutionContext(copiedActivity); this.executionContexts.Add(newExecutionContext); newExecutionContext.InitializeActivity(newExecutionContext.Activity); return newExecutionContext; } catch (Exception) { if (newExecutionContext != null) { this.CompleteExecutionContext(newExecutionContext); } else { activeContexts.Remove(copiedActivity); } throw; } } public void CompleteExecutionContext(ActivityExecutionContext childContext) { if (this.ownerContext == null) throw new ObjectDisposedException("ActivityExecutionContextManager"); CompleteExecutionContext(childContext, false); } public void CompleteExecutionContext(ActivityExecutionContext childContext, bool forcePersist) { if (this.ownerContext == null) throw new ObjectDisposedException("ActivityExecutionContextManager"); if (childContext == null) throw new ArgumentNullException("childContext"); if (childContext.Activity == null) throw new ArgumentException("childContext", SR.GetString(SR.Error_MissingActivityProperty)); if (childContext.Activity.ContextActivity == null) throw new ArgumentException("childContext", SR.GetString(SR.Error_MissingContextActivityProperty)); if (!this.executionContexts.Contains(childContext)) throw new ArgumentException(); if (childContext.Activity.ContextActivity.ExecutionStatus != ActivityExecutionStatus.Closed && childContext.Activity.ContextActivity.ExecutionStatus != ActivityExecutionStatus.Initialized) throw new InvalidOperationException(SR.GetString(System.Globalization.CultureInfo.CurrentCulture, SR.Error_CannotCompleteContext)); // make sure that this is in the active contexts collections ActivityExecutionContextInfo childContextInfo = childContext.Activity.ContextActivity.GetValue(Activity.ActivityExecutionContextInfoProperty) as ActivityExecutionContextInfo; IList activeContexts = (IList)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); if (activeContexts == null || !activeContexts.Contains(childContext.Activity.ContextActivity)) throw new ArgumentException(); // add it to completed contexts collection bool needsCompensation = childContext.Activity.NeedsCompensation; if (needsCompensation || forcePersist) { // add it to completed contexts List completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as List; if (completedContexts == null) { completedContexts = new List(); this.ownerContext.Activity.ContextActivity.SetValue(Activity.CompletedExecutionContextsProperty, completedContexts); } if (needsCompensation) childContextInfo.Flags = PersistFlags.NeedsCompensation; if (forcePersist) childContextInfo.Flags |= PersistFlags.ForcePersist; childContextInfo.SetCompletedOrderId(this.ownerContext.Activity.IncrementCompletedOrderId()); completedContexts.Add(childContextInfo); // ask runtime to save the context activity this.ownerContext.Activity.WorkflowCoreRuntime.SaveContextActivity(childContext.Activity); } // remove it from active contexts activeContexts.Remove(childContext.Activity.ContextActivity); this.executionContexts.Remove(childContext); //Case for those context which has compensatable child context, when those context //are completed at the end of Compensation chain we need to uninitialize the context //activity associated to them. if (childContext.Activity.ContextActivity.CanUninitializeNow && childContext.Activity.ContextActivity.ExecutionResult != ActivityExecutionResult.Uninitialized) { childContext.Activity.ContextActivity.Uninitialize(this.ownerContext.Activity.RootActivity.WorkflowCoreRuntime); childContext.Activity.ContextActivity.SetValue(Activity.ExecutionResultProperty, ActivityExecutionResult.Uninitialized); } // unregister it from runtime this.ownerContext.Activity.WorkflowCoreRuntime.UnregisterContextActivity(childContext.Activity); if (!(needsCompensation || forcePersist)) { childContext.Activity.Dispose(); } } public ActivityExecutionContext GetExecutionContext(Activity activity) { if (this.ownerContext == null) throw new ObjectDisposedException("ActivityExecutionContextManager"); if (activity == null) throw new ArgumentNullException("activity"); ActivityExecutionContextInfo contextInfo = activity.GetValue(Activity.ActivityExecutionContextInfoProperty) as ActivityExecutionContextInfo; // Returns the first context for an activity with the same qualified name. foreach (ActivityExecutionContext context in ExecutionContexts) { if (contextInfo == null) //Template being passed. { if (context.Activity.ContextActivity.QualifiedName == activity.QualifiedName) return context; } else //Context Sensitive Activity { if (context.ContextGuid.Equals(contextInfo.ContextGuid)) return context; } } return null; } public IEnumerable PersistedExecutionContexts { get { if (this.ownerContext == null) #pragma warning suppress 56503 throw new ObjectDisposedException("ActivityExecutionContextManager"); List completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as List; completedContexts = (completedContexts == null) ? new List() : completedContexts; List persistedContexts = new List(); foreach (ActivityExecutionContextInfo contextInfo in completedContexts) if ((contextInfo.Flags & PersistFlags.ForcePersist) != 0) persistedContexts.Add(contextInfo.ContextGuid); return persistedContexts; } } public ActivityExecutionContext GetPersistedExecutionContext(Guid contextGuid) { if (this.ownerContext == null) throw new ObjectDisposedException("ActivityExecutionContextManager"); // Check if child execution context exists. IList completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as IList; if (completedContexts == null) throw new ArgumentException(); ActivityExecutionContextInfo contextInfo = null; foreach (ActivityExecutionContextInfo completedContextInfo in completedContexts) { if (completedContextInfo.ContextGuid == contextGuid && ((completedContextInfo.Flags & PersistFlags.ForcePersist) != 0)) { contextInfo = completedContextInfo; break; } } if (contextInfo == null) throw new ArgumentException(); // The caller would have to close the AEC with forcepersist the next time // around. contextInfo.Flags &= ~PersistFlags.ForcePersist; return DiscardPersistedExecutionContext(contextInfo); } #endregion internal void Dispose() { if (this.ownerContext != null) { foreach (ActivityExecutionContext executionContext in this.ExecutionContexts) ((IDisposable)executionContext).Dispose(); this.ownerContext = null; } } #region Internal members internal ReadOnlyCollection CompletedExecutionContexts { get { List completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as List; completedContexts = (completedContexts == null) ? new List() : completedContexts; return completedContexts.AsReadOnly(); } } internal ActivityExecutionContext DiscardPersistedExecutionContext(ActivityExecutionContextInfo contextInfo) { if (contextInfo == null) throw new ArgumentNullException("contextInfo"); // check if child execution context IList completedContexts = this.ownerContext.Activity.ContextActivity.GetValue(Activity.CompletedExecutionContextsProperty) as IList; if (completedContexts == null || !completedContexts.Contains(contextInfo)) throw new ArgumentException(); // revoke from persistence service Activity revokedActivity = this.ownerContext.WorkflowCoreRuntime.LoadContextActivity(contextInfo, this.ownerContext.Activity.ContextActivity.GetActivityByName(contextInfo.ActivityQualifiedName)); ((IDependencyObjectAccessor)revokedActivity).InitializeInstanceForRuntime(this.ownerContext.Activity.WorkflowCoreRuntime); // add it back to active contexts IList activeContexts = (IList)this.ownerContext.Activity.ContextActivity.GetValue(Activity.ActiveExecutionContextsProperty); if (activeContexts == null) { activeContexts = new List(); this.ownerContext.Activity.ContextActivity.SetValue(Activity.ActiveExecutionContextsProperty, activeContexts); } activeContexts.Add(revokedActivity); // inform workflow runtime this.ownerContext.Activity.WorkflowCoreRuntime.RegisterContextActivity(revokedActivity); // return the new context ActivityExecutionContext revokedContext = new ActivityExecutionContext(revokedActivity); this.executionContexts.Add(revokedContext); System.Workflow.Runtime.WorkflowTrace.Runtime.TraceEvent(TraceEventType.Information, 0, "Revoking context {0}:{1}", revokedContext.ContextId, revokedContext.Activity.ContextActivity.QualifiedName); // remove it from completed contexts completedContexts.Remove(contextInfo); return revokedContext; } #endregion } #region Class ActivityExecutionContextInfo [Serializable] [Flags] internal enum PersistFlags : byte { NeedsCompensation = 1, ForcePersist = 2 } [Serializable] internal sealed class ActivityExecutionContextInfo { private string qualifiedID = string.Empty; private int contextId = -1; private Guid contextGuid = Guid.Empty; // private int parentContextId = -1; private int completedOrderId = -1; private PersistFlags flags = 0; internal ActivityExecutionContextInfo(string qualifiedName, int contextId, Guid contextGuid, int parentContextId) { this.qualifiedID = qualifiedName; this.contextId = contextId; this.contextGuid = contextGuid; this.parentContextId = parentContextId; } internal int ContextId { get { return this.contextId; } } public Guid ContextGuid { get { return this.contextGuid; } } public string ActivityQualifiedName { get { return this.qualifiedID; } } public int CompletedOrderId { get { return this.completedOrderId; } } internal int ParentContextId { get { return this.parentContextId; } } internal void SetCompletedOrderId(int completedOrderId) { this.completedOrderId = completedOrderId; } internal PersistFlags Flags { get { return this.flags; } set { this.flags = value; } } public override int GetHashCode() { return contextGuid.GetHashCode(); } public override bool Equals(object obj) { ActivityExecutionContextInfo otherContextInfo = obj as ActivityExecutionContextInfo; if (otherContextInfo != null) { return this.ContextGuid.Equals(otherContextInfo.ContextGuid); } return false; } } #endregion }