1 #pragma warning disable 1634, 1691
2 namespace System.Workflow.ComponentModel
7 using System.Collections;
8 using System.Collections.Specialized;
9 using System.Collections.Generic;
10 using System.Diagnostics;
11 using System.Globalization;
12 using System.ComponentModel;
13 using System.ComponentModel.Design;
14 using System.ComponentModel.Design.Serialization;
15 using System.Reflection;
16 using System.Workflow.ComponentModel.Compiler;
17 using System.Workflow.ComponentModel.Serialization;
18 using System.Workflow.ComponentModel.Design;
24 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
25 public sealed class WorkflowChanges
28 public static readonly DependencyProperty ConditionProperty = DependencyProperty.RegisterAttached("Condition", typeof(ActivityCondition), typeof(WorkflowChanges), new PropertyMetadata(DependencyPropertyOptions.Metadata));
29 internal static DependencyProperty WorkflowChangeActionsProperty = DependencyProperty.RegisterAttached("WorkflowChangeActions", typeof(IList), typeof(WorkflowChanges), new PropertyMetadata(DependencyPropertyOptions.NonSerialized));
30 internal static DependencyProperty WorkflowChangeVersionProperty = DependencyProperty.RegisterAttached("WorkflowChangeVersion", typeof(Guid), typeof(WorkflowChanges), new PropertyMetadata(Guid.Empty, DependencyPropertyOptions.NonSerialized));
32 private Activity originalRootActivity = null;
33 private Activity clonedRootActivity = null;
35 private List<WorkflowChangeAction> modelChangeActions = new List<WorkflowChangeAction>();
36 private bool saved = false;
40 #region Constuctor & Destructor
42 public WorkflowChanges(Activity rootActivity)
44 if (rootActivity == null)
45 throw new ArgumentNullException("rootActivity");
46 if (!(rootActivity is CompositeActivity) || rootActivity.Parent != null)
47 throw new ArgumentException(SR.GetString(SR.Error_RootActivityTypeInvalid2), "rootActivity");
48 #pragma warning suppress 56506
49 if (rootActivity.DesignMode)
50 throw new InvalidOperationException(SR.GetString(SR.Error_NoRuntimeAvailable));
52 // get the original activity
53 this.originalRootActivity = (Activity)((Activity)rootActivity).GetValue(Activity.WorkflowDefinitionProperty);
54 if (this.originalRootActivity == null)
55 this.originalRootActivity = rootActivity;
57 // Work around: for dynamic update create a clone, without calling initialize for runtime
58 this.clonedRootActivity = (Activity)CloneRootActivity(originalRootActivity);
60 // make the tree readonly
61 ApplyDynamicUpdateMode((Activity)this.clonedRootActivity);
66 #region Public members
67 // WhenConditionProperty Get and Set Accessors
68 public static object GetCondition(object dependencyObject)
70 if (dependencyObject == null)
71 throw new ArgumentNullException("dependencyObject");
72 if (!(dependencyObject is DependencyObject))
73 throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(DependencyObject).FullName), "dependencyObject");
75 return (dependencyObject as DependencyObject).GetValue(ConditionProperty);
78 public static void SetCondition(object dependencyObject, object value)
80 if (dependencyObject == null)
81 throw new ArgumentNullException("dependencyObject");
82 if (!(dependencyObject is DependencyObject))
83 throw new ArgumentException(SR.GetString(SR.Error_UnexpectedArgumentType, typeof(DependencyObject).FullName), "dependencyObject");
85 (dependencyObject as DependencyObject).SetValue(ConditionProperty, value);
88 public CompositeActivity TransientWorkflow
92 return this.clonedRootActivity as CompositeActivity;
96 public ValidationErrorCollection Validate()
98 TypeProvider typeProvider = CreateTypeProvider(this.originalRootActivity);
100 // create service provider
101 ServiceContainer serviceContainer = new ServiceContainer();
102 serviceContainer.AddService(typeof(ITypeProvider), typeProvider);
104 ValidationManager validationManager = new ValidationManager(serviceContainer);
105 ValidationErrorCollection errors;
106 using (WorkflowCompilationContext.CreateScope(validationManager))
108 errors = ValidationHelpers.ValidateObject(validationManager, this.clonedRootActivity);
110 return XomlCompilerHelper.MorphIntoFriendlyValidationErrors(errors);
115 ValidationErrorCollection errors = Validate();
116 if (errors.HasErrors)
117 throw new WorkflowValidationFailedException(SR.GetString(SR.Error_CompilerValidationFailed), errors);
119 //work around !!!for conditions we do diff
120 object originalConditions = ((Activity)this.originalRootActivity).GetValue(ConditionTypeConverter.DeclarativeConditionDynamicProp);
121 object changedConditions = ((Activity)this.clonedRootActivity).GetValue(ConditionTypeConverter.DeclarativeConditionDynamicProp);
122 if (null != originalConditions)
123 this.modelChangeActions.AddRange(((IWorkflowChangeDiff)originalConditions).Diff(originalConditions, changedConditions));
124 else if (null != changedConditions)
125 this.modelChangeActions.AddRange(((IWorkflowChangeDiff)changedConditions).Diff(originalConditions, changedConditions));
127 // diff the process model
128 this.modelChangeActions.AddRange(DiffTrees(this.originalRootActivity as CompositeActivity, this.clonedRootActivity as CompositeActivity));
130 // always call it after diff tree, otherwise it turns on the Locked.
131 ReleaseDynamicUpdateMode((Activity)this.clonedRootActivity);
133 // cache the change actions into the new workflow definition
134 ArrayList workflowChanges = (ArrayList)((Activity)this.clonedRootActivity).GetValue(WorkflowChanges.WorkflowChangeActionsProperty);
135 if (workflowChanges == null)
137 workflowChanges = new ArrayList();
138 ((Activity)this.clonedRootActivity).SetValue(WorkflowChanges.WorkflowChangeActionsProperty, workflowChanges);
141 workflowChanges.AddRange(this.modelChangeActions);
142 ((Activity)this.clonedRootActivity).SetValue(WorkflowChanges.WorkflowChangeVersionProperty, Guid.NewGuid());
145 // now initialize for runtime
146 ((IDependencyObjectAccessor)this.clonedRootActivity).InitializeDefinitionForRuntime(null);
149 internal void ApplyTo(Activity activity)
151 if (activity == null)
152 throw new ArgumentNullException("activity");
154 if (activity.Parent != null)
155 throw new ArgumentException(SR.GetString(SR.Error_RootActivityTypeInvalid), "activity");
157 if (activity.RootActivity == null)
158 throw new InvalidOperationException(SR.GetString(SR.Error_MissingRootActivity));
160 if (activity.WorkflowCoreRuntime == null)
161 throw new InvalidOperationException(SR.GetString(SR.Error_NoRuntimeAvailable));
164 throw new InvalidOperationException(SR.GetString(SR.Error_TransactionAlreadyApplied));
166 if (!CompareWorkflowDefinition((Activity)this.originalRootActivity, (Activity)activity.RootActivity.GetValue(Activity.WorkflowDefinitionProperty)))
167 throw new ArgumentException(SR.GetString(SR.Error_WorkflowDefinitionModified), "activity");
171 // go up in the chain and then apply changes
172 IWorkflowCoreRuntime workflowCoreRuntime = activity.WorkflowCoreRuntime;
173 if (workflowCoreRuntime.CurrentAtomicActivity != null)
174 throw new InvalidOperationException(SR.GetString(SR.Error_InsideAtomicScope));
175 bool suspended = workflowCoreRuntime.SuspendInstance(SR.GetString(SR.SuspendReason_WorkflowChange));
178 // collect all context Activities
179 List<Activity> contextActivities = new List<Activity>();
180 Queue<Activity> contextActivitiesQueue = new Queue<Activity>();
181 contextActivitiesQueue.Enqueue(workflowCoreRuntime.RootActivity);
182 while (contextActivitiesQueue.Count > 0)
184 Activity contextActivity = contextActivitiesQueue.Dequeue();
185 contextActivities.Add(contextActivity);
187 // enqueue child context Activities
188 IList<Activity> nestedContextActivities = (IList<Activity>)contextActivity.GetValue(Activity.ActiveExecutionContextsProperty);
189 if (nestedContextActivities != null)
191 foreach (Activity nestedContextActivity in nestedContextActivities)
192 contextActivitiesQueue.Enqueue(nestedContextActivity);
196 // run instance level validations
197 ValidationErrorCollection validationErrors = new ValidationErrorCollection();
198 foreach (WorkflowChangeAction changeAction in this.modelChangeActions)
200 if (changeAction is ActivityChangeAction)
202 foreach (Activity contextActivity in contextActivities)
204 // WinOE Bug 16903: Ask the contextActivity itself whether or not it can be removed.
205 // An activity can not be removed if it's in the executing mode.
206 if (changeAction is RemovedActivityAction &&
207 contextActivity.DottedPath == ((RemovedActivityAction)changeAction).OriginalRemovedActivity.DottedPath)
208 validationErrors.AddRange(changeAction.ValidateChanges(contextActivity));
210 // Ask the parent context activity whether or not this child activity can be added or removed.
211 // The call to TraverseDottedPathFromRoot here should return the parent context activity for this change action.
212 if (contextActivity.TraverseDottedPathFromRoot(((ActivityChangeAction)changeAction).OwnerActivityDottedPath) != null)
213 validationErrors.AddRange(changeAction.ValidateChanges(contextActivity));
218 // if errors then return
219 if (validationErrors.HasErrors)
220 throw new WorkflowValidationFailedException(SR.GetString(SR.Error_RuntimeValidationFailed), validationErrors);
222 // verify if workflow can be changed
223 VerifyWorkflowCanBeChanged(workflowCoreRuntime);
225 // inform workflow runtime
226 workflowCoreRuntime.OnBeforeDynamicChange(this.modelChangeActions);
228 // set the new Workflow Definition
229 workflowCoreRuntime.RootActivity.SetValue(Activity.WorkflowDefinitionProperty, this.clonedRootActivity);
231 // apply changes to all context Activities
232 foreach (Activity contextActivity in contextActivities)
234 // apply change to state reader
235 foreach (WorkflowChangeAction changeAction in this.modelChangeActions)
237 if (changeAction is ActivityChangeAction)
239 if (contextActivity.TraverseDottedPathFromRoot(((ActivityChangeAction)changeAction).OwnerActivityDottedPath) != null)
241 bool result = changeAction.ApplyTo(contextActivity);
242 Debug.Assert(result, "ApplyTo failed");
246 // fixup meta properties and notify changes
247 // if the context activity is the one that's being removed, we do not fixup the meta properties.
248 Activity clonedActivity = ((Activity)this.clonedRootActivity).GetActivityByName(contextActivity.QualifiedName);
249 if (clonedActivity != null)
250 contextActivity.FixUpMetaProperties(clonedActivity);
251 NotifyChangesToChildExecutors(workflowCoreRuntime, contextActivity, this.modelChangeActions);
252 NotifyChangesCompletedToChildExecutors(workflowCoreRuntime, contextActivity);
255 // inform workflow runtime
256 workflowCoreRuntime.OnAfterDynamicChange(true, this.modelChangeActions);
260 workflowCoreRuntime.OnAfterDynamicChange(false, this.modelChangeActions);
266 workflowCoreRuntime.Resume();
273 #region Internal Helpers
274 private void OnActivityListChanged(object sender, ActivityCollectionChangeEventArgs e)
276 if (e.RemovedItems != null)
278 foreach (Activity removedActivity in e.RemovedItems)
280 if (removedActivity.Readonly)
281 ReleaseDynamicUpdateMode(removedActivity);
285 private void ApplyDynamicUpdateMode(Activity seedActivity)
287 Queue<Activity> queue = new Queue<Activity>();
288 queue.Enqueue(seedActivity);
289 while (queue.Count > 0)
291 Activity activity = queue.Dequeue();
292 activity.Readonly = true;
293 activity.DynamicUpdateMode = true;
294 foreach (DependencyProperty dependencyProperty in activity.MetaDependencyProperties)
296 if (activity.IsBindingSet(dependencyProperty))
298 ActivityBind activityBind = activity.GetBinding(dependencyProperty);
299 if (activityBind != null)
300 activityBind.DynamicUpdateMode = true;
304 if (activity is CompositeActivity)
306 CompositeActivity compositeActivity = activity as CompositeActivity;
307 compositeActivity.Activities.ListChanged += new EventHandler<ActivityCollectionChangeEventArgs>(this.OnActivityListChanged);
308 foreach (Activity activity2 in ((CompositeActivity)activity).Activities)
309 queue.Enqueue(activity2);
313 private void ReleaseDynamicUpdateMode(Activity seedActivity)
315 Queue<Activity> queue = new Queue<Activity>();
316 queue.Enqueue(seedActivity);
317 while (queue.Count > 0)
319 Activity activity = queue.Dequeue() as Activity;
320 activity.Readonly = false;
321 activity.DynamicUpdateMode = false;
322 foreach (DependencyProperty dependencyProperty in activity.MetaDependencyProperties)
324 if (activity.IsBindingSet(dependencyProperty))
326 ActivityBind activityBind = activity.GetBinding(dependencyProperty);
327 if (activityBind != null)
328 activityBind.DynamicUpdateMode = false;
331 if (activity is CompositeActivity)
333 CompositeActivity compositeActivity = activity as CompositeActivity;
334 compositeActivity.Activities.ListChanged -= new EventHandler<ActivityCollectionChangeEventArgs>(this.OnActivityListChanged);
335 foreach (Activity activity2 in ((CompositeActivity)activity).Activities)
336 queue.Enqueue(activity2);
340 private void VerifyWorkflowCanBeChanged(IWorkflowCoreRuntime workflowCoreRuntime)
342 // check if the update is allowed on this root-activity.
343 ActivityCondition dynamicUpdateCondition = ((Activity)workflowCoreRuntime.RootActivity).GetValue(WorkflowChanges.ConditionProperty) as ActivityCondition;
344 if (dynamicUpdateCondition != null)
346 using (workflowCoreRuntime.SetCurrentActivity(workflowCoreRuntime.RootActivity))
348 if (!dynamicUpdateCondition.Evaluate(workflowCoreRuntime.RootActivity, workflowCoreRuntime))
349 throw new InvalidOperationException(SR.GetString(CultureInfo.CurrentCulture, SR.Error_DynamicUpdateEvaluation, new object[] { workflowCoreRuntime.InstanceID.ToString() }));
353 private void NotifyChangesCompletedToChildExecutors(IWorkflowCoreRuntime workflowCoreRuntime, Activity contextActivity)
355 Queue compositeActivities = new Queue();
356 compositeActivities.Enqueue(contextActivity);
357 while (compositeActivities.Count > 0)
359 CompositeActivity compositeActivity = compositeActivities.Dequeue() as CompositeActivity;
360 if (compositeActivity == null || !WorkflowChanges.IsActivityExecutable(compositeActivity))
363 ISupportWorkflowChanges compositeActivityExecutor = ActivityExecutors.GetActivityExecutor(compositeActivity) as ISupportWorkflowChanges;
364 if (compositeActivityExecutor != null)
366 using (workflowCoreRuntime.SetCurrentActivity(compositeActivity))
368 using (ActivityExecutionContext executionContext = new ActivityExecutionContext(compositeActivity))
369 compositeActivityExecutor.OnWorkflowChangesCompleted(executionContext);
372 foreach (Activity activity in compositeActivity.Activities)
374 if (activity is CompositeActivity)
375 compositeActivities.Enqueue(activity);
381 internal static bool IsActivityExecutable(Activity activity)
383 if (!activity.Enabled)
385 if (activity.Parent != null)
386 return IsActivityExecutable(activity.Parent);
387 return activity.Enabled;
390 private void NotifyChangesToChildExecutors(IWorkflowCoreRuntime workflowCoreRuntime, Activity contextActivity, IList<WorkflowChangeAction> changeActions)
392 foreach (WorkflowChangeAction action in changeActions)
394 if (!(action is ActivityChangeAction))
397 CompositeActivity ownerActivity = contextActivity.TraverseDottedPathFromRoot(((ActivityChangeAction)action).OwnerActivityDottedPath) as CompositeActivity;
398 if (ownerActivity == null || !WorkflowChanges.IsActivityExecutable(ownerActivity))
401 ISupportWorkflowChanges compositeActivityExecutor = ActivityExecutors.GetActivityExecutor(ownerActivity) as ISupportWorkflowChanges;
402 if (compositeActivityExecutor == null)
403 throw new ApplicationException(SR.GetString(SR.Error_WorkflowChangesNotSupported, ownerActivity.GetType().FullName));
405 using (workflowCoreRuntime.SetCurrentActivity(ownerActivity))
407 using (ActivityExecutionContext executionContext = new ActivityExecutionContext(ownerActivity))
409 if (action is AddedActivityAction)
411 Activity addedActivity = ownerActivity.Activities[((AddedActivityAction)action).Index];
412 if (WorkflowChanges.IsActivityExecutable(addedActivity))
414 addedActivity.OnActivityExecutionContextLoad(executionContext.Activity.RootActivity.WorkflowCoreRuntime);
415 executionContext.InitializeActivity(addedActivity);
416 compositeActivityExecutor.OnActivityAdded(executionContext, addedActivity);
419 else if (action is RemovedActivityAction)
421 RemovedActivityAction removedActivityAction = (RemovedActivityAction)action;
422 if (WorkflowChanges.IsActivityExecutable(removedActivityAction.OriginalRemovedActivity))
424 compositeActivityExecutor.OnActivityRemoved(executionContext, removedActivityAction.OriginalRemovedActivity);
425 if (removedActivityAction.OriginalRemovedActivity.ExecutionResult != ActivityExecutionResult.Uninitialized)
427 removedActivityAction.OriginalRemovedActivity.Uninitialize(executionContext.Activity.RootActivity.WorkflowCoreRuntime);
428 removedActivityAction.OriginalRemovedActivity.SetValue(Activity.ExecutionResultProperty, ActivityExecutionResult.Uninitialized);
430 removedActivityAction.OriginalRemovedActivity.OnActivityExecutionContextUnload(executionContext.Activity.RootActivity.WorkflowCoreRuntime);
431 removedActivityAction.OriginalRemovedActivity.Dispose();
440 #region Static helpers
442 private static bool CompareWorkflowDefinition(Activity originalWorkflowDefinition, Activity currentWorkflowDefinition)
444 if (originalWorkflowDefinition == currentWorkflowDefinition)
447 if (originalWorkflowDefinition.GetType() != currentWorkflowDefinition.GetType())
450 Guid originalChangeVersion = (Guid)originalWorkflowDefinition.GetValue(WorkflowChanges.WorkflowChangeVersionProperty);
451 Guid currentChangeVersion = (Guid)currentWorkflowDefinition.GetValue(WorkflowChanges.WorkflowChangeVersionProperty);
452 return (originalChangeVersion == currentChangeVersion);
455 private static List<WorkflowChangeAction> DiffTrees(CompositeActivity originalCompositeActivity, CompositeActivity clonedCompositeActivity)
457 List<WorkflowChangeAction> listChanges = new List<WorkflowChangeAction>();
458 IEnumerator<Activity> clonedActivitiesEnum = clonedCompositeActivity.Activities.GetEnumerator();
459 IEnumerator<Activity> originalActivitiesEnum = originalCompositeActivity.Activities.GetEnumerator();
460 int currentRemoveIndex = 0;
461 while (originalActivitiesEnum.MoveNext())
463 bool foundMatching = false;
464 Activity originalActivity = originalActivitiesEnum.Current;
465 while (clonedActivitiesEnum.MoveNext())
467 Activity clonedActivity = clonedActivitiesEnum.Current;
468 if (clonedActivity.Readonly)
470 if (originalActivity.DottedPath == clonedActivity.CachedDottedPath)
472 currentRemoveIndex++;
473 foundMatching = true;
474 if (originalActivity is CompositeActivity)
475 listChanges.AddRange(DiffTrees(originalActivity as CompositeActivity, clonedActivity as CompositeActivity));
480 listChanges.Add(new RemovedActivityAction(currentRemoveIndex, originalActivity, clonedCompositeActivity));
481 while (originalActivitiesEnum.MoveNext())
483 originalActivity = originalActivitiesEnum.Current;
484 if (originalActivity.DottedPath == clonedActivity.CachedDottedPath)
486 currentRemoveIndex++;
487 foundMatching = true;
488 if (originalActivity is CompositeActivity)
489 listChanges.AddRange(DiffTrees(originalActivity as CompositeActivity, clonedActivity as CompositeActivity));
494 listChanges.Add(new RemovedActivityAction(currentRemoveIndex, originalActivity, clonedCompositeActivity));
502 listChanges.Add(new AddedActivityAction(clonedCompositeActivity, clonedActivity));
503 currentRemoveIndex++;
508 listChanges.Add(new RemovedActivityAction(currentRemoveIndex, originalActivity, clonedCompositeActivity));
511 while (clonedActivitiesEnum.MoveNext())
512 listChanges.Add(new AddedActivityAction(clonedCompositeActivity, clonedActivitiesEnum.Current));
516 private static Activity CloneRootActivity(Activity originalRootActivity)
518 // create new definition root
519 string xomlText = originalRootActivity.GetValue(Activity.WorkflowXamlMarkupProperty) as string;
520 string rulesText = null;
521 Activity clonedRootActivity = null;
522 IServiceProvider serviceProvider = originalRootActivity.GetValue(Activity.WorkflowRuntimeProperty) as IServiceProvider;
523 Debug.Assert(serviceProvider != null);
524 if (!string.IsNullOrEmpty(xomlText))
526 rulesText = originalRootActivity.GetValue(Activity.WorkflowRulesMarkupProperty) as string;
527 clonedRootActivity = Activity.OnResolveActivityDefinition(null, xomlText, rulesText, true, false, serviceProvider);
530 clonedRootActivity = Activity.OnResolveActivityDefinition(originalRootActivity.GetType(), null, null, true, false, serviceProvider);
532 if (clonedRootActivity == null)
533 throw new NullReferenceException(SR.GetString(SR.Error_InvalidRootForWorkflowChanges));
535 // deserialize change history and apply it to new definition tree
536 ArrayList workflowChanges = (ArrayList)((Activity)originalRootActivity).GetValue(WorkflowChanges.WorkflowChangeActionsProperty);
537 if (workflowChanges != null)
539 workflowChanges = CloneWorkflowChangeActions(workflowChanges, originalRootActivity);
540 if (workflowChanges != null)
542 // apply changes to the shared schedule Defn to get the instance specific copy
543 foreach (WorkflowChangeAction action in workflowChanges)
545 bool result = action.ApplyTo((Activity)clonedRootActivity);
546 Debug.Assert(result, "ApplyTo Failed");
548 ((Activity)clonedRootActivity).SetValue(WorkflowChanges.WorkflowChangeActionsProperty, workflowChanges);
551 return clonedRootActivity;
554 private static ArrayList CloneWorkflowChangeActions(ArrayList workflowChanges, Activity rootActivity)
556 if (workflowChanges == null)
557 throw new ArgumentNullException("workflowChanges");
559 if (rootActivity == null)
560 throw new ArgumentNullException("rootActivity");
562 string dynamicUpdateHistory = null;
563 TypeProvider typeProvider = CreateTypeProvider(rootActivity);
564 ServiceContainer serviceContainer = new ServiceContainer();
565 serviceContainer.AddService(typeof(ITypeProvider), typeProvider);
566 DesignerSerializationManager manager = new DesignerSerializationManager(serviceContainer);
567 WorkflowMarkupSerializer xomlSerializer = new WorkflowMarkupSerializer();
569 ArrayList clonedWorkflowChanges = null;
570 // serialize dynamic updates
571 using (manager.CreateSession())
573 using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
575 using (XmlWriter xmlWriter = Helpers.CreateXmlWriter(sw))
577 WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
578 xomlSerializer.Serialize(xomlSerializationManager, xmlWriter, workflowChanges);
579 dynamicUpdateHistory = sw.ToString();
584 using (StringReader sr = new StringReader(dynamicUpdateHistory))
586 using (XmlReader xmlReader = XmlReader.Create(sr))
588 WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
589 clonedWorkflowChanges = xomlSerializer.Deserialize(xomlSerializationManager, xmlReader) as ArrayList;
593 return clonedWorkflowChanges;
596 internal static TypeProvider CreateTypeProvider(Activity rootActivity)
598 TypeProvider typeProvider = new TypeProvider(null);
600 Type companionType = rootActivity.GetType();
601 typeProvider.SetLocalAssembly(companionType.Assembly);
602 typeProvider.AddAssembly(companionType.Assembly);
604 foreach (AssemblyName assemblyName in companionType.Assembly.GetReferencedAssemblies())
606 Assembly referencedAssembly = null;
609 referencedAssembly = Assembly.Load(assemblyName);
610 if (referencedAssembly != null)
611 typeProvider.AddAssembly(referencedAssembly);
617 if (referencedAssembly == null && assemblyName.CodeBase != null)
618 typeProvider.AddAssemblyReference(assemblyName.CodeBase);
625 #region WorkflowChangeAction classes
627 [DesignerSerializer(typeof(WorkflowMarkupSerializer), typeof(WorkflowMarkupSerializer))]
628 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
629 public abstract class WorkflowChangeAction
631 protected internal abstract bool ApplyTo(Activity rootActivity);
632 protected internal abstract ValidationErrorCollection ValidateChanges(Activity activity);
635 [DesignerSerializer(typeof(ActivityChangeActionMarkupSerializer), typeof(WorkflowMarkupSerializer))]
636 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
637 public abstract class ActivityChangeAction : WorkflowChangeAction
639 private string ownerActivityDottedPath = string.Empty;
641 protected ActivityChangeAction()
645 protected ActivityChangeAction(CompositeActivity compositeActivity)
647 if (compositeActivity == null)
648 throw new ArgumentNullException("compositeActivity");
650 this.ownerActivityDottedPath = compositeActivity.DottedPath;
653 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
654 public string OwnerActivityDottedPath
658 return this.ownerActivityDottedPath;
662 this.ownerActivityDottedPath = value;
666 protected internal override ValidationErrorCollection ValidateChanges(Activity contextActivity)
668 if (contextActivity == null)
669 throw new ArgumentNullException("contextActivity");
671 ValidationErrorCollection errors = new ValidationErrorCollection();
673 CompositeActivity ownerActivity = contextActivity.TraverseDottedPathFromRoot(this.OwnerActivityDottedPath) as CompositeActivity;
674 if (ownerActivity != null && WorkflowChanges.IsActivityExecutable(ownerActivity))
676 foreach (Validator validator in ComponentDispenser.CreateComponents(ownerActivity.GetType(), typeof(ActivityValidatorAttribute)))
678 ValidationError error = validator.ValidateActivityChange(ownerActivity, this);
688 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
689 public sealed class AddedActivityAction : ActivityChangeAction
691 private int index = 0;
692 private Activity addedActivity = null;
694 public AddedActivityAction()
698 public AddedActivityAction(CompositeActivity compositeActivity, Activity activityAdded)
699 : base(compositeActivity)
701 if (compositeActivity == null)
702 throw new ArgumentNullException("compositeActivity");
704 if (activityAdded == null)
705 throw new ArgumentNullException("activityAdded");
707 this.index = (compositeActivity.Activities != null) ? compositeActivity.Activities.IndexOf(activityAdded) : -1;
708 this.addedActivity = activityAdded;
722 public Activity AddedActivity
726 return this.addedActivity;
730 this.addedActivity = value;
734 protected internal override bool ApplyTo(Activity rootActivity)
736 if (rootActivity == null)
737 throw new ArgumentNullException("rootActivity");
738 if (!(rootActivity is CompositeActivity))
739 throw new ArgumentException(SR.GetString(SR.Error_RootActivityTypeInvalid), "rootActivity");
741 CompositeActivity ownerActivity = rootActivity.TraverseDottedPathFromRoot(this.OwnerActivityDottedPath) as CompositeActivity;
742 if (ownerActivity == null)
746 ownerActivity.DynamicUpdateMode = true;
747 CompositeActivity addedActivityOwner = this.addedActivity.Parent;
750 this.addedActivity.SetParent(ownerActivity);
751 Activity clonedAddedActivity = this.addedActivity;
752 if (!this.addedActivity.DesignMode)
753 clonedAddedActivity = this.addedActivity.Clone();
754 // We need to serialize and deserialize in order to clone during design mode
757 TypeProvider typeProvider = WorkflowChanges.CreateTypeProvider(rootActivity);
758 ServiceContainer serviceContainer = new ServiceContainer();
759 serviceContainer.AddService(typeof(ITypeProvider), typeProvider);
760 DesignerSerializationManager manager = new DesignerSerializationManager(serviceContainer);
761 WorkflowMarkupSerializer xomlSerializer = new WorkflowMarkupSerializer();
762 string addedActivityText = string.Empty;
763 // serialize dynamic updates
764 using (manager.CreateSession())
766 using (StringWriter sw = new StringWriter(CultureInfo.InvariantCulture))
768 using (XmlWriter xmlWriter = Helpers.CreateXmlWriter(sw))
770 WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
771 xomlSerializer.Serialize(xomlSerializationManager, xmlWriter, this.addedActivity);
772 addedActivityText = sw.ToString();
777 using (StringReader sr = new StringReader(addedActivityText))
779 using (XmlReader xmlReader = XmlReader.Create(sr))
781 WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
782 clonedAddedActivity = xomlSerializer.Deserialize(xomlSerializationManager, xmlReader) as Activity;
786 if (clonedAddedActivity == null)
787 throw new InvalidOperationException(SR.GetString(SR.Error_ApplyDynamicChangeFailed));
789 if (ownerActivity.WorkflowCoreRuntime != null)
790 ((IDependencyObjectAccessor)clonedAddedActivity).InitializeInstanceForRuntime(ownerActivity.WorkflowCoreRuntime);
792 clonedAddedActivity.SetParent(null);
793 ownerActivity.Activities.Insert(this.index, clonedAddedActivity);
797 this.addedActivity.SetParent(addedActivityOwner);
798 ownerActivity.DynamicUpdateMode = false;
804 [Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
805 public sealed class RemovedActivityAction : ActivityChangeAction
807 private int removedActivityIndex = -1;
808 private Activity originalRemovedActivity = null;
810 public RemovedActivityAction()
813 public RemovedActivityAction(int removedActivityIndex, Activity originalActivity, CompositeActivity clonedParentActivity)
814 : base(clonedParentActivity)
816 if (originalActivity == null)
817 throw new ArgumentNullException("originalActivity");
818 if (clonedParentActivity == null)
819 throw new ArgumentNullException("clonedParentActivity");
821 this.originalRemovedActivity = originalActivity;
822 this.removedActivityIndex = removedActivityIndex;
825 [DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
826 public int RemovedActivityIndex
830 return this.removedActivityIndex;
834 this.removedActivityIndex = value;
837 [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
838 public Activity OriginalRemovedActivity
842 return this.originalRemovedActivity;
846 this.originalRemovedActivity = value;
849 protected internal override ValidationErrorCollection ValidateChanges(Activity contextActivity)
851 ValidationErrorCollection errors = base.ValidateChanges(contextActivity);
852 Activity removedActivityInContext = contextActivity.TraverseDottedPathFromRoot(this.originalRemovedActivity.DottedPath);
853 if (WorkflowChanges.IsActivityExecutable(removedActivityInContext) && removedActivityInContext.ExecutionStatus == ActivityExecutionStatus.Executing)
854 errors.Add(new ValidationError(SR.GetString(SR.Error_RemoveExecutingActivity, this.originalRemovedActivity.QualifiedName), ErrorNumbers.Error_RemoveExecutingActivity));
857 protected internal override bool ApplyTo(Activity rootActivity)
859 if (rootActivity == null)
860 throw new ArgumentNullException("rootActivity");
861 if (!(rootActivity is CompositeActivity))
862 throw new ArgumentException(SR.GetString(SR.Error_RootActivityTypeInvalid), "rootActivity");
865 CompositeActivity ownerActivity = rootActivity.TraverseDottedPathFromRoot(this.OwnerActivityDottedPath) as CompositeActivity;
866 if (ownerActivity == null)
869 if (this.removedActivityIndex >= ownerActivity.Activities.Count)
873 ownerActivity.DynamicUpdateMode = true;
876 this.originalRemovedActivity = ownerActivity.Activities[this.removedActivityIndex];
877 ownerActivity.Activities.RemoveAt(this.removedActivityIndex);
881 ownerActivity.DynamicUpdateMode = false;
888 #region Class ActivityChangeActionMarkupSerializer
889 internal sealed class ActivityChangeActionMarkupSerializer : WorkflowMarkupSerializer
891 protected internal override PropertyInfo[] GetProperties(WorkflowMarkupSerializationManager serializationManager, object obj)
893 List<PropertyInfo> properties = new List<PropertyInfo>(base.GetProperties(serializationManager, obj));
895 //Collect the internal properties, we do this so that activity change action apis don't need to expose unnecessary setters
896 foreach (PropertyInfo property in obj.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.FlattenHierarchy))
898 DesignerSerializationVisibility visibility = Helpers.GetSerializationVisibility(property);
899 if (visibility != DesignerSerializationVisibility.Hidden && property.GetSetMethod() == null && property.GetSetMethod(true) != null)
900 properties.Add(property);
903 return properties.ToArray();