/// <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);
        }
Example #2
0
        /// <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");
            }
        }