#pragma warning disable 1634, 1691 namespace System.Workflow.Activities { #region Using directives using System; using System.Xml.Serialization; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.CodeDom; using System.Diagnostics; using System.ComponentModel.Design; using System.Drawing; using System.Drawing.Design; using System.Transactions; using System.ComponentModel.Design.Serialization; using System.Workflow.ComponentModel; using System.Workflow.ComponentModel.Design; using System.Workflow.ComponentModel.Compiler; using System.Reflection; using System.Workflow.Runtime.DebugEngine; using System.Workflow.Activities.Common; #endregion [SRDescription(SR.ReplicatorActivityDescription)] [ToolboxItem(typeof(ActivityToolboxItem))] [ToolboxBitmap(typeof(ReplicatorActivity), "Resources.Replicator.png")] [Designer(typeof(ReplicatorDesigner), typeof(IDesigner))] [ActivityValidator(typeof(ReplicatorValidator))] [DefaultEvent("Initialized")] [WorkflowDebuggerSteppingAttribute(WorkflowDebuggerSteppingOption.Concurrent)] [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] public sealed class ReplicatorActivity : CompositeActivity { #region Dependency Properties public static readonly DependencyProperty UntilConditionProperty = DependencyProperty.Register("UntilCondition", typeof(ActivityCondition), typeof(ReplicatorActivity), new PropertyMetadata(DependencyPropertyOptions.Metadata)); public static readonly DependencyProperty ExecutionTypeProperty = DependencyProperty.Register("ExecutionType", typeof(ExecutionType), typeof(ReplicatorActivity), new PropertyMetadata(ExecutionType.Sequence)); //events public static readonly DependencyProperty InitializedEvent = DependencyProperty.Register("Initialized", typeof(EventHandler), typeof(ReplicatorActivity)); public static readonly DependencyProperty CompletedEvent = DependencyProperty.Register("Completed", typeof(EventHandler), typeof(ReplicatorActivity)); public static readonly DependencyProperty ChildInitializedEvent = DependencyProperty.Register("ChildInitialized", typeof(EventHandler), typeof(ReplicatorActivity)); public static readonly DependencyProperty ChildCompletedEvent = DependencyProperty.Register("ChildCompleted", typeof(EventHandler), typeof(ReplicatorActivity)); public static readonly DependencyProperty InitialChildDataProperty = DependencyProperty.Register("InitialChildData", typeof(IList), typeof(ReplicatorActivity)); #endregion #region Constructors public ReplicatorActivity() { } public ReplicatorActivity(string name) : base(name) { } #endregion #region Public Properties [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public ICollection DynamicActivities { get { if (this.EnabledActivities.Count > 0) return this.GetDynamicActivities(this.EnabledActivities[0]); else return new Activity[0]; } } [Browsable(true)] [SRCategory(SR.Properties)] [SRDescription(SR.ExecutionTypeDescr)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] public ExecutionType ExecutionType { get { return (ExecutionType)base.GetValue(ReplicatorActivity.ExecutionTypeProperty); } set { if (value != ExecutionType.Sequence && value != ExecutionType.Parallel) throw new ArgumentOutOfRangeException("value"); if (this.ActivityState != null && this.ActivityState.IsChildActive) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorChildRunning)); base.SetValue(ReplicatorActivity.ExecutionTypeProperty, value); } } [Editor(typeof(BindUITypeEditor), typeof(UITypeEditor))] [Browsable(true)] [SRCategory(SR.Properties)] [SRDescription(SR.InitialChildDataDescr)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)] [DefaultValue(null)] public IList InitialChildData { get { return base.GetValue(InitialChildDataProperty) as IList; } set { base.SetValue(InitialChildDataProperty, value); } } ReplicatorChildInstanceList childDataList; [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public IList CurrentChildData { get { if (childDataList == null) childDataList = new ReplicatorChildInstanceList(this); return childDataList; } } [SRCategory(SR.Conditions)] [SRDescription(SR.ReplicatorUntilConditionDescr)] [DefaultValue(null)] public ActivityCondition UntilCondition { get { return base.GetValue(UntilConditionProperty) as ActivityCondition; } set { base.SetValue(UntilConditionProperty, value); } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public bool AllChildrenComplete { get { if (this.ActivityState != null) return !this.ActivityState.IsChildActive; else return true; } } [Browsable(false)] [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)] public int CurrentIndex { get { if (this.ActivityState != null) { if (this.ExecutionType == ExecutionType.Sequence) return this.ActivityState.CurrentIndex; else return this.ActivityState.AbsoluteCount - 1; } else return -1; } } public bool IsExecuting(int index) { if (this.ActivityState != null) { if (index < 0 || index >= this.ActivityState.AbsoluteCount) throw new ArgumentOutOfRangeException("index"); ChildExecutionStateInfo childStateInfo = this.ActivityState[index, false]; return (childStateInfo.Status == ChildRunStatus.PendingExecute || childStateInfo.Status == ChildRunStatus.Running); } return false; } #endregion #region Public Events [SRDescription(SR.OnGeneratorChildInitializedDescr)] [SRCategory(SR.Handlers)] [MergableProperty(false)] public event EventHandler ChildInitialized { add { base.AddHandler(ChildInitializedEvent, value); } remove { base.RemoveHandler(ChildInitializedEvent, value); } } [SRDescription(SR.OnGeneratorChildCompletedDescr)] [SRCategory(SR.Handlers)] [MergableProperty(false)] public event EventHandler ChildCompleted { add { base.AddHandler(ChildCompletedEvent, value); } remove { base.RemoveHandler(ChildCompletedEvent, value); } } [SRDescription(SR.OnCompletedDescr)] [SRCategory(SR.Handlers)] [MergableProperty(false)] public event EventHandler Completed { add { base.AddHandler(CompletedEvent, value); } remove { base.RemoveHandler(CompletedEvent, value); } } [SRDescription(SR.OnInitializedDescr)] [SRCategory(SR.Handlers)] [MergableProperty(false)] public event EventHandler Initialized { add { base.AddHandler(InitializedEvent, value); } remove { base.RemoveHandler(InitializedEvent, value); } } #endregion #region ChildList Manipulation API private int Add(object value) { if (this.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (this.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); ChildExecutionStateInfo childStateInfo = new ChildExecutionStateInfo(value); this.ActivityState.Add(childStateInfo); int indexOfAdd = this.ActivityState.AbsoluteCount - 1; ScheduleExecutionIfNeeded(childStateInfo, indexOfAdd); return indexOfAdd; } private int IndexOf(object value) { if (this.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (this.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); int absoluteIndex = 0; for (int i = 0; i < this.ActivityState.Count; ++i) { ChildExecutionStateInfo childStateInfo = this.ActivityState[i]; if (!childStateInfo.MarkedForRemoval) { if (Object.Equals(childStateInfo.InstanceData, value)) return absoluteIndex; else ++absoluteIndex; } } return -1; } private void Insert(int index, object value) { if (value == null) throw new ArgumentNullException("value"); if (this.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (this.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); if (index < 0 || index > this.ActivityState.AbsoluteCount) throw new ArgumentOutOfRangeException("index"); ChildExecutionStateInfo childStateInfo = new ChildExecutionStateInfo(value); this.ActivityState.Insert(index, childStateInfo, false); ScheduleExecutionIfNeeded(childStateInfo, index); } private void Remove(object obj) { int index = this.IndexOf(obj); if (index < 0) return; RemoveAt(index); return; } private void RemoveAt(int index) { if (this.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (this.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); if (index < 0 || index >= this.ActivityState.AbsoluteCount) throw new ArgumentOutOfRangeException("index"); ChildExecutionStateInfo childStateInfo = this.ActivityState[index, false]; if (childStateInfo.Status == ChildRunStatus.Completed || childStateInfo.Status == ChildRunStatus.Created) this.ActivityState.Remove(childStateInfo); else { childStateInfo.MarkedForRemoval = true; base.Invoke(this.HandleChildUpdateOperation, new ReplicatorInterActivityEventArgs(childStateInfo, false)); } } private void Clear() { if (this.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (this.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); while (this.ActivityState.AbsoluteCount != 0) this.RemoveAt(0); } #endregion #region Protected Methods protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { if (executionContext == null) throw new ArgumentNullException("executionContext"); this.ActivityState = new ReplicatorStateInfo(); base.RaiseEvent(ReplicatorActivity.InitializedEvent, this, EventArgs.Empty); if (this.InitialChildData != null) { //Add the ChildData to the execution info. for (int i = 0; i < this.InitialChildData.Count; ++i) { this.Add(this.InitialChildData[i]); } } bool bCompleteNow = (this.UntilCondition == null); if (this.UntilCondition != null && this.UntilCondition.Evaluate(this, executionContext)) bCompleteNow = true; else if (this.ActivityState.Count != 0) bCompleteNow = false; if (bCompleteNow) { //This is needed to make sure we dont reevaluate this again. this.ActivityState.CompletionConditionTrueAlready = true; //Try cool down child. It is ok to close here immediatley //since we are sure we havent executed child yet. if (!TryCancelChildren(executionContext)) { base.RaiseEvent(ReplicatorActivity.CompletedEvent, this, EventArgs.Empty); return ActivityExecutionStatus.Closed; } } return ActivityExecutionStatus.Executing; } protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext) { if (executionContext == null) throw new ArgumentNullException("executionContext"); this.TryCancelChildren(executionContext); if (!this.ActivityState.IsChildActive) { //Check to make sure only once we call ReplciatorCompleted when we fault. if (this.ExecutionStatus == ActivityExecutionStatus.Faulting) { if (this.ActivityState.AttemptedCloseWhileFaulting) return ActivityExecutionStatus.Closed; this.ActivityState.AttemptedCloseWhileFaulting = true; } base.RaiseEvent(ReplicatorActivity.CompletedEvent, this, EventArgs.Empty); return ActivityExecutionStatus.Closed; } return this.ExecutionStatus; } protected override void OnClosed(IServiceProvider provider) { // } #endregion #region Private Implementation #region Data //Runtime State Properties static DependencyProperty ActivityStateProperty = DependencyProperty.Register("ActivityState", typeof(ReplicatorStateInfo), typeof(ReplicatorActivity)); ReplicatorStateInfo ActivityState { get { return (ReplicatorStateInfo)base.GetValue(ActivityStateProperty); } set { base.SetValue(ActivityStateProperty, value); } } #endregion #region Replicator Interactivity Event private sealed class ReplicatorInterActivityEventArgs : EventArgs { #region Data private bool isAdd = false; private ChildExecutionStateInfo childStateInfo; #endregion #region Properties internal bool IsAdd { get { return this.isAdd; } } internal ChildExecutionStateInfo ChildStateInfo { get { return this.childStateInfo; } } #endregion internal ReplicatorInterActivityEventArgs(ChildExecutionStateInfo childStateInfo, bool isAdd) { this.childStateInfo = childStateInfo; this.isAdd = isAdd; } } void HandleChildUpdateOperation(Object sender, ReplicatorInterActivityEventArgs e) { if (sender == null) throw new ArgumentNullException("sender"); ActivityExecutionContext executionContext = sender as ActivityExecutionContext; if (executionContext == null) throw new ArgumentException(SR.Error_SenderMustBeActivityExecutionContext, "sender"); if (this.ExecutionStatus != ActivityExecutionStatus.Executing) return; if (!e.IsAdd) { CancelChildExecution(executionContext, e.ChildStateInfo); } else { Debug.Assert(this.ActivityState.Contains(e.ChildStateInfo)); Debug.Assert(e.ChildStateInfo.Status == ChildRunStatus.PendingExecute); ExecuteTemplate(executionContext, e.ChildStateInfo); } } private void CancelChildExecution(ActivityExecutionContext executionContext, ChildExecutionStateInfo childStateInfo) { // Mark the Instance For Removal System.Diagnostics.Debug.Assert(childStateInfo.MarkedForRemoval); // check if the instance is currently executing if (childStateInfo.Status != ChildRunStatus.Running) //It is passive, then we can safely remove the State. { this.ActivityState.Remove(childStateInfo); return; } // schedule the child cancellation // once this run is cancelled, the handleEvent should remove this from execution state. TryCancelChild(executionContext, childStateInfo); } #endregion #region Execution related helpers private void ExecuteTemplate(ActivityExecutionContext executionContext, ChildExecutionStateInfo childStateInfo) { System.Diagnostics.Debug.Assert(childStateInfo.Status != ChildRunStatus.Running); ActivityExecutionContextManager contextManager = executionContext.ExecutionContextManager; ActivityExecutionContext templateExecutionContext = contextManager.CreateExecutionContext(this.EnabledActivities[0]); childStateInfo.RunId = templateExecutionContext.ContextGuid; childStateInfo.Status = ChildRunStatus.Running; try { base.RaiseGenericEvent(ReplicatorActivity.ChildInitializedEvent, this, new ReplicatorChildEventArgs(childStateInfo.InstanceData, templateExecutionContext.Activity)); } catch { childStateInfo.RunId = Guid.Empty; childStateInfo.Status = ChildRunStatus.Completed; contextManager.CompleteExecutionContext(templateExecutionContext); throw; } templateExecutionContext.ExecuteActivity(templateExecutionContext.Activity); templateExecutionContext.Activity.RegisterForStatusChange(Activity.ClosedEvent, new ReplicatorSubscriber(this, templateExecutionContext.ContextGuid)); } private void HandleStatusChange(ActivityExecutionContext executionContext, ActivityExecutionStatusChangedEventArgs e, ReplicatorSubscriber subscriber) { //System.Diagnostics.Debug.Assert(this.ExecutionStatus != ActivityExecutionStatus.Closed, "Stale notification should not have reache here"); //System.Diagnostics.Debug.Assert(e.Activity.QualifiedName.Equals(this.EnabledActivities[0].QualifiedName), "Got status change notification of non existing child"); //System.Diagnostics.Debug.Assert(subscriber.RunIdentifier != Guid.Empty, "Got notification from non-running template instance"); //Perform cleanup on completed run. int runIndex = this.ActivityState.FindIndexOfChildStateInfo(subscriber.RunIdentifier); if (runIndex == -1) { //This will happen when CancelChild is issued after Child Closed //but before StatusChange Event raised on parent. return; } ChildExecutionStateInfo childStateInfo = this.ActivityState[runIndex]; bool isMarkedForRemoval = childStateInfo.MarkedForRemoval; try { try { base.RaiseGenericEvent(ReplicatorActivity.ChildCompletedEvent, this, new ReplicatorChildEventArgs(childStateInfo.InstanceData, e.Activity)); e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, subscriber); } finally { ActivityExecutionContextManager contextManager = executionContext.ExecutionContextManager; ActivityExecutionContext templateExecutionContext = contextManager.GetExecutionContext(e.Activity); contextManager.CompleteExecutionContext(templateExecutionContext); } //Reevaluate CompletionCondition if (!this.ActivityState.CompletionConditionTrueAlready) this.ActivityState.CompletionConditionTrueAlready = (this.UntilCondition != null && this.UntilCondition.Evaluate(this, executionContext)); } finally //Always perform cleanup of just completed child. { //This will mark child as passive. childStateInfo.RunId = Guid.Empty; childStateInfo.Status = ChildRunStatus.Completed; if (isMarkedForRemoval) { //This is the case, when user issued CancelChild request on running template instance. //We flush out execution state of that run when it becomes passive. this.ActivityState.Remove(childStateInfo); runIndex = runIndex - 1; //Needed for sequence execution type. } } //Next Step. if (!this.ActivityState.IsChildActive) //Everything is passive now. { if (this.ExecutionStatus == ActivityExecutionStatus.Canceling || this.ExecutionStatus == ActivityExecutionStatus.Faulting || this.ActivityState.CompletionConditionTrueAlready) { base.RaiseEvent(ReplicatorActivity.CompletedEvent, this, EventArgs.Empty); executionContext.CloseActivity(); return; } } else //Template is active; Valid only for parallel { System.Diagnostics.Debug.Assert(this.ExecutionType == ExecutionType.Parallel); if (this.ExecutionStatus != ActivityExecutionStatus.Canceling && this.ExecutionStatus != ActivityExecutionStatus.Faulting) { if (this.ActivityState.CompletionConditionTrueAlready) { //Try cool down child. TryCancelChildren(executionContext); return; } } } switch (this.ExecutionType) { case ExecutionType.Sequence: if (runIndex < this.ActivityState.Count - 1) { ExecuteTemplate(executionContext, this.ActivityState[runIndex + 1]); return; } else if (this.UntilCondition == null || this.UntilCondition.Evaluate(this, executionContext)) { base.RaiseEvent(ReplicatorActivity.CompletedEvent, this, EventArgs.Empty); executionContext.CloseActivity(); return; } break; case ExecutionType.Parallel: if (!this.ActivityState.IsChildActive && (this.UntilCondition == null || (this.UntilCondition.Evaluate(this, executionContext)))) { base.RaiseEvent(ReplicatorActivity.CompletedEvent, this, EventArgs.Empty); executionContext.CloseActivity(); return; } break; default: throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorInvalidExecutionType)); } } bool TryCancelChildren(ActivityExecutionContext executionContext) { // returns true iff scheduled cancel on one or more executions of the template // false if all executions are already closed if (this.ActivityState == null) return false; ReplicatorStateInfo stateInfo = this.ActivityState; bool fScheduledCancel = false; for (int i = 0; i < stateInfo.Count; ++i) { if (this.TryCancelChild(executionContext, stateInfo[i])) { fScheduledCancel = true; } } return fScheduledCancel; } bool TryCancelChild(ActivityExecutionContext outerProvider, ChildExecutionStateInfo childStateInfo) { // schedule cancellation of the child in the inner execution context bool fScheduledCancel = false; // returns true iff scheduled cancel on one execution of the template // false if execution already closed // get the execution context for this run ActivityExecutionContextManager contextManager = outerProvider.ExecutionContextManager; ActivityExecutionContext innerProvider = GetExecutionContext(contextManager, childStateInfo.RunId); if (innerProvider != null) { switch (innerProvider.Activity.ExecutionStatus) { case ActivityExecutionStatus.Executing: // schedule cancellation on child innerProvider.CancelActivity(innerProvider.Activity); fScheduledCancel = true; break; case ActivityExecutionStatus.Canceling: case ActivityExecutionStatus.Faulting: fScheduledCancel = true; break; default: // do nothing break; } } else { //Finish the run if it is pending for execution. if (this.ExecutionStatus != ActivityExecutionStatus.Executing && childStateInfo.Status == ChildRunStatus.PendingExecute) childStateInfo.Status = ChildRunStatus.Completed; } return fScheduledCancel; } private ActivityExecutionContext GetExecutionContext(ActivityExecutionContextManager contextManager, Guid contextIdGuid) { foreach (ActivityExecutionContext context in contextManager.ExecutionContexts) if (context.ContextGuid == contextIdGuid) return context; return null; } //Schedules execution if mode is parallel or if the insert is at head of empty list //or tail of all completed list in sequence case. void ScheduleExecutionIfNeeded(ChildExecutionStateInfo childStateInfo, int index) { bool bShouldExecute = (this.ExecutionType == ExecutionType.Parallel); if (!bShouldExecute) //Sequence Case. { //Execute if its head and only node or tail and previous tail already completed. int totalListSize = this.ActivityState.AbsoluteCount; if ((index == 0 && totalListSize == 1) || ((index == totalListSize - 1) && this.ActivityState[totalListSize - 2, false].Status == ChildRunStatus.Completed)) bShouldExecute = true; } if (bShouldExecute) { childStateInfo.Status = ChildRunStatus.PendingExecute; base.Invoke(this.HandleChildUpdateOperation, new ReplicatorInterActivityEventArgs(childStateInfo, true)); } } #endregion #region Execution related Data structures [Serializable] class ReplicatorSubscriber : IActivityEventListener { #region Data private Guid runId; internal Guid RunIdentifier { get { return this.runId; } } #endregion internal ReplicatorSubscriber(Activity ownerActivity, Guid runIdentifier) : base() { this.runId = runIdentifier; } #region IActivityEventListener Members void IActivityEventListener.OnEvent(object sender, ActivityExecutionStatusChangedEventArgs e) { if (sender == null) throw new ArgumentNullException("sender"); ActivityExecutionContext context = sender as ActivityExecutionContext; if (context == null) throw new ArgumentException(SR.Error_SenderMustBeActivityExecutionContext, "sender"); // ((ReplicatorActivity)context.Activity).HandleStatusChange(context, e, this); } #endregion #region Object Overrides public override bool Equals(object obj) { ReplicatorSubscriber subscriber = obj as ReplicatorSubscriber; return (subscriber != null && base.Equals(obj) && (this.runId.Equals(subscriber.runId))); } public override int GetHashCode() { return base.GetHashCode() ^ this.runId.GetHashCode(); } #endregion } [Serializable] class ReplicatorStateInfo : List { //Fields / Properties internal bool CompletionConditionTrueAlready = false; internal bool AttemptedCloseWhileFaulting = false; internal bool IsChildActive { get { for (int i = 0; i < this.Count; ++i) { ChildExecutionStateInfo childStateInfo = this[i]; if (childStateInfo.Status == ChildRunStatus.Running || childStateInfo.Status == ChildRunStatus.PendingExecute) return true; } return false; } } internal int CurrentIndex { get { for (int i = 0; i < this.AbsoluteCount; ++i) { if (this[i, false].RunId != Guid.Empty) return i; } return this.AbsoluteCount - 1; } } //Helper Methods internal int FindIndexOfChildStateInfo(Guid runId) { for (int i = 0; i < this.Count; ++i) { ChildExecutionStateInfo childStateInfo = this[i]; if (childStateInfo.RunId == runId) return i; } Debug.Assert(false, "Child State Info not Found for the RunID"); throw new IndexOutOfRangeException(); } internal ChildExecutionStateInfo this[int index, bool includeStaleEntries] { get { if (includeStaleEntries) return this[index]; for (int i = 0; i < this.Count; ++i) { if (!this[i].MarkedForRemoval && index-- == 0) return this[i]; } throw new IndexOutOfRangeException(); } } internal void Insert(int index, ChildExecutionStateInfo value, bool includeStaleEntries) { if (includeStaleEntries) { Insert(index, value); return; } int indexOfInsert = 0; for (indexOfInsert = 0; (indexOfInsert < this.Count) && index > 0; ++indexOfInsert) { if (!this[indexOfInsert].MarkedForRemoval) --index; } if (index == 0) Insert(indexOfInsert, value); else throw new IndexOutOfRangeException(); } internal int Add(ChildExecutionStateInfo value, bool includeStaleEntries) { base.Add(value); if (includeStaleEntries) return base.Count - 1; else return this.AbsoluteCount - 1; } internal int AbsoluteCount { get { int absoluteCount = 0; int counter = 0; while (counter < this.Count) { if (!this[counter++].MarkedForRemoval) ++absoluteCount; } return absoluteCount; } } } [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] enum ChildRunStatus : byte { Created, PendingExecute, Running, Completed } [Serializable] class ChildExecutionStateInfo { Object data; Guid runId; bool markedForRemoval; ChildRunStatus status; internal ChildRunStatus Status { get { return this.status; } set { this.status = value; } } internal Object InstanceData { get { return this.data; } set { this.data = value; } } internal Guid RunId { get { return this.runId; } set { this.runId = value; } } internal bool MarkedForRemoval { get { return this.markedForRemoval; } set { this.markedForRemoval = value; } } internal ChildExecutionStateInfo(Object instanceData) { this.data = instanceData; this.markedForRemoval = false; this.status = ChildRunStatus.Created; } } #endregion #endregion #region Replicator Child List Implementation [Serializable] private sealed class ReplicatorChildInstanceList : IList { ReplicatorActivity replicatorActivity; internal ReplicatorChildInstanceList(ReplicatorActivity replicatorActivity) { this.replicatorActivity = replicatorActivity; } #region IList Members int IList.Add(object value) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); return replicatorActivity.Add(value); } void IList.Clear() { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); replicatorActivity.Clear(); } bool IList.Contains(object value) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); return replicatorActivity.IndexOf(value) != -1; } int IList.IndexOf(object value) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); return replicatorActivity.IndexOf(value); } void IList.Insert(int index, object value) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); replicatorActivity.Insert(index, value); } bool IList.IsFixedSize { get { return false; } } bool IList.IsReadOnly { get { return false; } } void IList.Remove(object value) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); replicatorActivity.Remove(value); } void IList.RemoveAt(int index) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); replicatorActivity.RemoveAt(index); } object IList.this[int index] { get { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); if (replicatorActivity.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (replicatorActivity.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); return replicatorActivity.ActivityState[index, false].InstanceData; } set { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); if (replicatorActivity.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (replicatorActivity.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); replicatorActivity.ActivityState[index, false].InstanceData = value; } } #endregion #region ICollection Members void ICollection.CopyTo(Array array, int index) { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); if (replicatorActivity.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (replicatorActivity.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); if (array == null) throw new ArgumentNullException("array"); if (array.Rank != 1) throw new ArgumentException(SR.GetString(SR.Error_MultiDimensionalArray), "array"); if (index < 0) throw new ArgumentOutOfRangeException("index"); if (array.Length - index < replicatorActivity.ActivityState.AbsoluteCount) throw new ArgumentException(SR.GetString(SR.Error_InsufficientArrayPassedIn), "array"); for (int i = 0; i < replicatorActivity.ActivityState.AbsoluteCount; ++i) { array.SetValue(replicatorActivity.ActivityState[i, false].InstanceData, i + index); } } int ICollection.Count { get { #pragma warning disable 56503 if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); if (replicatorActivity.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (replicatorActivity.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); return replicatorActivity.ActivityState.AbsoluteCount; #pragma warning restore 56503 } } bool ICollection.IsSynchronized { get { return false; } } object ICollection.SyncRoot { get { #pragma warning disable 56503 throw new NotImplementedException(); #pragma warning restore 56503 } } #endregion #region IEnumerable Members IEnumerator IEnumerable.GetEnumerator() { if (replicatorActivity == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorDisconnected)); if (replicatorActivity.ExecutionStatus != ActivityExecutionStatus.Executing) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotExecuting)); if (replicatorActivity.ActivityState == null) throw new InvalidOperationException(SR.GetString(SR.Error_ReplicatorNotInitialized)); for (int i = 0; i < replicatorActivity.ActivityState.AbsoluteCount; ++i) yield return replicatorActivity.ActivityState[i, false].InstanceData; } #endregion } #endregion } #region ReplicatorEventArgs [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] public sealed class ReplicatorChildEventArgs : EventArgs { private object instanceData = null; private Activity activity = null; public ReplicatorChildEventArgs(object instanceData, Activity activity) { this.instanceData = instanceData; this.activity = activity; } public object InstanceData { get { return this.instanceData; } } public Activity Activity { get { return this.activity; } } } #endregion #region Execution Type Enum [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")] public enum ExecutionType { Sequence = 0, Parallel = 1 } #endregion #region Validator internal sealed class ReplicatorValidator : CompositeActivityValidator { public override ValidationErrorCollection Validate(ValidationManager manager, object obj) { ValidationErrorCollection validationErrors = base.Validate(manager, obj); ReplicatorActivity replicator = obj as ReplicatorActivity; if (replicator == null) throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(ReplicatorActivity).FullName), "obj"); if ((replicator.EnabledActivities.Count != 1)) validationErrors.Add(new ValidationError(SR.GetString(SR.Error_GeneratorShouldContainSingleActivity), ErrorNumbers.Error_GeneratorShouldContainSingleActivity)); return validationErrors; } } #endregion }