void OnChildStateComplete(NativeActivityContext context, ActivityInstance instance, string targetStateId) { InternalState completedState = (InternalState)instance.Activity; this.hasRunningChildState.Set(context, false); //When child state is completed, current state become the deepest child state. this.EventManager.Get(context).CompleteDeepestChildBookmark = this.completeStateBookmark.Get(context); switch (instance.State) { case ActivityInstanceState.Closed: Debug.Assert(!completedState.IsFinal, "Final state is only on root level."); if (StateMachineHelper.IsAncestor(this.StateId, targetStateId)) { ScheduleChildState(context, targetStateId); } else { //The target state does not belong to this state or the target state equals this state. //In this case, this state should be completed. PrepareForExit(context, targetStateId); } break; case ActivityInstanceState.Canceled: if (this.currentRunningTriggers.Get(context) == 0) { ScheduleExit(context); } break; } }
protected override void CacheMetadata(NativeActivityMetadata metadata) { //clean up this.internalStates.Clear(); this.internalStateFuncs.Clear(); this.internalTransitions.Clear(); StateMachineHelper.ProcessChildStates(metadata, this.States, this.internalStates, this.internalStateFuncs); if (this.Entry != null) { metadata.AddChild(this.Entry); } if (this.Exit != null) { metadata.AddChild(this.Exit); } ProcessTransitions(metadata); metadata.AddArgument(new RuntimeArgument("ToState", this.ToState.ArgumentType, ArgumentDirection.In)); metadata.AddArgument(new RuntimeArgument("EventManager", this.EventManager.ArgumentType, ArgumentDirection.In)); metadata.AddImplementationVariable(this.currentRunningTriggers); metadata.AddImplementationVariable(this.hasRunningChildState); metadata.AddImplementationVariable(this.isExiting); metadata.AddImplementationVariable(this.evaluateConditionBookmark); metadata.AddImplementationVariable(this.completeStateBookmark); }
void OnStateComplete(NativeActivityContext context, ActivityInstance completedInstance, string result) { if (StateMachineHelper.IsAncestor(rootId, result)) { int index = StateMachineHelper.GetChildStateIndex(rootId, result); context.ScheduleFunc <string, StateMachineEventManager, string>(this.internalStateFuncs[index], result, this.eventManager.Get(context), onStateComplete); } }
void ScheduleChildState(NativeActivityContext context, string id) { int index = StateMachineHelper.GetChildStateIndex(this.StateId, id); Debug.Assert(index >= 0 && index < this.internalStateFuncs.Count); context.ScheduleFunc <string, StateMachineEventManager, string>(this.internalStateFuncs[index], id, this.EventManager.Get(context), this.onChildStateComplete); this.hasRunningChildState.Set(context, true); }
protected override void Execute(NativeActivityContext context) { //We view the duration before moving to initial state is on transition. StateMachineEventManager localEventManager = this.eventManager.Get(context); localEventManager.OnTransition = true; int index = StateMachineHelper.GetChildStateIndex(rootId, this.InitialState.StateId); context.ScheduleFunc <string, StateMachineEventManager, string>(this.internalStateFuncs[index], this.InitialState.StateId, localEventManager, onStateComplete); }
/// <summary> /// Do validation and if validation is successful, create internal representations for states and transitions. /// </summary> protected override void CacheMetadata(NativeActivityMetadata metadata) { //cleanup this.internalStateFuncs.Clear(); this.internalStates.Clear(); //clear Ids and Flags via transitions this.PassNumber++; TraverseViaTransitions(ClearState, ClearTransition); //clear Ids and Flags via children this.PassNumber++; TraverseViaChildren(ClearStates, null, ClearTransitions, false); //Mark via children and do some check this.PassNumber++; TraverseViaChildren(MarkStatesViaChildren, delegate(State state) { StateCannotHaveMultipleParents(metadata, state); }, null, false); this.PassNumber++; //Mark via transition TraverseViaTransitions(delegate(State state) { MarkStateViaTransition(metadata, state); }, null); //Do validation via children //need not check the violation of state which is not reached this.PassNumber++; TraverseViaChildren(delegate(Collection <State> states) { ValidateStates(metadata, states); }, null, delegate(State state) { ValidateTransitions(metadata, state); }, true); //Validate the root state machine itself ValidateStateMachine(metadata); if (!metadata.HasViolations) { StateMachineHelper.ProcessChildStates(metadata, this.States, this.internalStates, this.internalStateFuncs); } metadata.AddImplementationVariable(this.eventManager); foreach (Variable variable in this.Variables) { metadata.AddVariable(variable); } }
static void ValidateTransitions(NativeActivityMetadata metadata, State currentState) { Collection <Transition> transitions = currentState.Transitions; HashSet <Activity> conditionalTransitionTriggers = new HashSet <Activity>(); Dictionary <Activity, List <Transition> > unconditionalTransitionMapping = new Dictionary <Activity, List <Transition> >(); foreach (Transition transition in transitions) { if (transition.Source != null) { metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, SR.TransitionCannotBeAddedTwice, transition.DisplayName, currentState.DisplayName, transition.Source.DisplayName)); continue; } else { transition.Source = currentState; } if (transition.To == null) { metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, SR.TransitionTargetCannotBeNull, transition.DisplayName, currentState.DisplayName)); } else { if (transition.To.States.Count > 0) { metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, SR.TargetStateMustBeSimpleState, transition.To.DisplayName, transition.DisplayName)); } if (StateMachineHelper.IsAncestor(currentState.StateId, transition.To.StateId)) { metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, SR.AncestorCannotHaveTransitionToDescendant, currentState.DisplayName, transition.DisplayName, transition.To.DisplayName)); } } if (transition.Trigger != null) { if (transition.Condition == null) { if (!unconditionalTransitionMapping.ContainsKey(transition.Trigger)) { unconditionalTransitionMapping.Add(transition.Trigger, new List <Transition>()); } unconditionalTransitionMapping[transition.Trigger].Add(transition); } else { conditionalTransitionTriggers.Add(transition.Trigger); } } else { metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, SR.TriggerCannotBeNull, transition.DisplayName, currentState.DisplayName)); } } foreach (KeyValuePair <Activity, List <Transition> > unconditionalTransitions in unconditionalTransitionMapping) { if (conditionalTransitionTriggers.Contains(unconditionalTransitions.Key) || unconditionalTransitions.Value.Count > 1) { foreach (Transition transition in unconditionalTransitions.Value) { metadata.AddValidationError(string.Format(CultureInfo.CurrentCulture, SR.UnconditionalTransitionShouldnotShareTriggersWithOthers, transition.DisplayName, currentState.DisplayName, transition.Trigger.DisplayName)); } } ; } }