private static bool ValidateDUInUnconditionalTransition(NativeActivityUpdateMapMetadata metadata, InternalTransition updatedTransition, InternalTransition originalTransition, out string errorMessage) { Fx.Assert(originalTransition.IsUnconditional, "Transition should be unconditional in the original definition."); Activity originalAction = originalTransition.TransitionDataList[0].Action; foreach (TransitionData transitionData in updatedTransition.TransitionDataList) { Activity updatedAction = transitionData.Action; Activity actionMatch = metadata.GetMatch(updatedAction); Activity conditionMatch = metadata.GetMatch(transitionData.Condition); if ((null == originalAction && null != actionMatch) || (null != originalAction && null != actionMatch && !object.ReferenceEquals(originalAction, actionMatch))) { // Transition.Action is an activity moved from elsewhere within the InternalState errorMessage = SR.MovingActivitiesInStateBlockDU; return false; } } errorMessage = string.Empty; metadata.SaveOriginalValue(updatedTransition.Trigger, originalTransition.InternalTransitionIndex); return true; }
protected override void OnCreateDynamicUpdateMap(NativeActivityUpdateMapMetadata metadata, Activity originalActivity) { Flowchart originalFlowchart = (Flowchart)originalActivity; Dictionary <Activity, int> originalActivities = new Dictionary <Activity, int>(); foreach (FlowNode node in originalFlowchart.reachableNodes) { if (node.ChildActivity == null) { continue; } if (metadata.IsReferenceToImportedChild(node.ChildActivity)) { // We can't save original values for referenced children. Also, we can't // reliably combine implementation changes with changes to referenced children. // For now, we just disable this scenario altogether; if we want to support it, // we'll need deeper runtime support. metadata.DisallowUpdateInsideThisActivity(SR.FlowchartContainsReferences); return; } if (originalActivities.ContainsKey(node.ChildActivity)) { metadata.DisallowUpdateInsideThisActivity(SR.MultipleFlowNodesSharingSameChildBlockDU); return; } originalActivities[node.ChildActivity] = node.Index; } HashSet <Activity> updatedActivities = new HashSet <Activity>(); foreach (FlowNode node in this.reachableNodes) { if (node.ChildActivity != null) { if (metadata.IsReferenceToImportedChild(node.ChildActivity)) { metadata.DisallowUpdateInsideThisActivity(SR.FlowchartContainsReferences); return; } if (updatedActivities.Contains(node.ChildActivity)) { metadata.DisallowUpdateInsideThisActivity(SR.MultipleFlowNodesSharingSameChildBlockDU); return; } else { updatedActivities.Add(node.ChildActivity); } Activity originalChild = metadata.GetMatch(node.ChildActivity); int originalIndex; if (originalChild != null && originalActivities.TryGetValue(originalChild, out originalIndex)) { if (originalFlowchart.reachableNodes[originalIndex].GetType() != node.GetType()) { metadata.DisallowUpdateInsideThisActivity(SR.CannotMoveChildAcrossDifferentFlowNodeTypes); return; } if (originalIndex != node.Index) { metadata.SaveOriginalValue(node.ChildActivity, originalIndex); } } } } }
private static bool ValidateDUInConditionTransition(NativeActivityUpdateMapMetadata metadata, InternalTransition updatedTransition, InternalTransition originalTransition, out string errorMessage) { Fx.Assert(!originalTransition.IsUnconditional, "Transition should be conditional in the original definition."); errorMessage = string.Empty; foreach (TransitionData updatedTData in updatedTransition.TransitionDataList) { if (metadata.IsReferenceToImportedChild(updatedTData.Condition)) { // if the trigger is referenced, it might have another save values already. errorMessage = SR.TriggerOrConditionIsReferenced; return false; } Fx.Assert(null != updatedTData.Condition, "Must be a condition transition."); Activity conditionMatch = metadata.GetMatch(updatedTData.Condition); if (null == conditionMatch && null != metadata.GetMatch(updatedTData.Action)) { // new Transition.Condition with an Transition.Action moved from within the InternalState. errorMessage = SR.MovingActivitiesInStateBlockDU; return false; } else if (null != conditionMatch) { bool foundMatchingOriginalCondition = false; for (int transitionIndex = 0; transitionIndex < originalTransition.TransitionDataList.Count; transitionIndex++) { if (object.ReferenceEquals(originalTransition.TransitionDataList[transitionIndex].Condition, conditionMatch)) { foundMatchingOriginalCondition = true; // found the original matching condition in updated transition definition. TransitionData originalTData = originalTransition.TransitionDataList[transitionIndex]; Activity originalAction = originalTData.Action; // NOTE: Transition.Action is allowed to be removed, because it doesn't change the execution semantics of SM // if this removed activity was executing, WF runtime would disallow the update. Activity actionMatch = metadata.GetMatch(updatedTData.Action); if (null != actionMatch && !object.ReferenceEquals(originalAction, actionMatch)) { // Transition.Action is an activity moved from elsewhere within the InternalState errorMessage = SR.MovingActivitiesInStateBlockDU; return false; } metadata.SaveOriginalValue(updatedTransition.Trigger, originalTransition.InternalTransitionIndex); metadata.SaveOriginalValue(updatedTData.Condition, transitionIndex); } } if (!foundMatchingOriginalCondition) { // another child activity is move to the Transition.Condition. errorMessage = SR.DUDisallowIfCannotFindingMatchingCondition; return false; } } } return true; }