/// <summary> /// Add a new transition to the collection of transitions from this state. /// </summary> /// <param name="TransitionToAdd">The transition to add.</param> /// <exception cref="ArgumentException">Thrown if the event in TransitionToAdd has already been used in a transition from this state.</exception> public void AddTransition(FiniteStateTransition TransitionToAdd) { string key = TransitionToAdd.ViaEvent.Name; if (Transitions.ContainsKey(key)) { throw new ArgumentException($"Duplicate event name='{key}' used to create a transition from state name='{Name}'."); } Transitions.Add(key, TransitionToAdd); }
/// <summary> /// Starts the state machine. /// /// Every state diagram has a start state with a single transition to some initial state in the diagram via a start event. /// This method performs the following actions: /// * creates the start state /// * creates the start event /// * adds a transition from the start state, via the start event to InitialState, the finite state passed as a parameter /// * sets the current state to be the start state /// * raises the start event /// The OnEntry event handler for InitialState will be executed. /// The state machine is now sitting in it's initial state and waiting for an event to occur. /// /// On a technical note, the underlying Thread, in which the event handlers are run, is also created and started here. /// </summary> /// <param name="InitialState">The finite state in which this state machine starts.</param> /// <exception cref="ArgumentException">Thrown if the parameter InitialState is a finite state that has not been added by <see cref="AddState(FiniteState)"/></exception> public void Start(FiniteState InitialState) { string methodName = System.Reflection.MethodBase.GetCurrentMethod().Name; if (log.IsDebugEnabled) { log.Debug($"{methodName}: enter"); } //if (OnExceptionAction == null) //{ // throw new ArgumentException($"The state machine must have an OnExceptionAction before you can start it."); //} // // Perform sanity checks // foreach (KeyValuePair <string, FiniteState> kvp in ManagedStates) { // // 1. Make sure each finite state has an OnEnterAction // FiniteState finiteState = kvp.Value; if (finiteState.OnEnterAction == null) { throw new Exception($"The finite state, '{finiteState.Name}' does not have an OnEnterAction."); } // // 2. Make sure the target state in every transition has been added to the state machine. // foreach (KeyValuePair <string, FiniteStateTransition> transitionKvp in finiteState.Transitions) { FiniteStateTransition fst = transitionKvp.Value; string stateName = fst.ToState.Name; if (!ManagedStates.ContainsKey(stateName)) { throw new Exception($"The finite state, '{stateName}' has not been added to the state machine."); } } } FiniteState startState = new FiniteState(START_STATE_NAME); FiniteStateEvent startEvent = new FiniteStateEvent(START_EVENT_NAME); startState.OnEnterAction = () => { }; // needs an empty handler AddState(startState); startState.AddTransition(startEvent, InitialState); SetCurrentState(startState); RaiseEvent(startEvent); //Thread runner = new Thread(RunStateMachine) //{ // Name = Name //}; //runner.Start(); if (log.IsDebugEnabled) { log.Debug($"{methodName}: exit"); } }