コード例 #1
0
ファイル: StateMachine.cs プロジェクト: sjvannTMU/Sage
        /// <summary>
        /// Creates a state machine that references a Model. Many of the event
        /// delegates send a model reference with the notification.
        /// </summary>
        /// <param name="model">The model to which this State Machine belongs.</param>
        /// <param name="transitionMatrix">A matrix of booleans. 'From' states are the
        /// row indices, and 'To' states are the column indices. The contents of a given
        /// cell in the matrix indicates whether that transition is permissible.</param>
        /// <param name="followOnStates">An array of enumerations of states, indicating
        /// which transition should occur automatically, if any, after transition into
        /// a given state has completed successfully.</param>
        /// <param name="initialState">Specifies the state in the state machine that is
        /// to be the initial state.</param>
        public StateMachine(IModel model, bool[,] transitionMatrix, Enum[] followOnStates, Enum initialState)
        {
            m_model      = model;
            m_enumValues = Enum.GetValues(initialState.GetType());
            InitializeStateTranslationTable(initialState);
            if (transitionMatrix.GetLength(0) != transitionMatrix.GetLength(1))
            {
                throw new ApplicationException("Transition matrix must be square.");
            }
            m_currentState    = GetStateNumber(initialState);
            m_2DTransitions   = new ITransitionHandler[m_numStates, m_numStates];
            m_transitionsFrom = new ITransitionHandler[m_numStates];
            m_transitionsTo   = new ITransitionHandler[m_numStates];
            m_stateMethods    = new StateMethod[m_numStates];

            m_followOnStates = followOnStates;

            for (int i = 0; i < m_numStates; i++)
            {
                m_transitionsFrom[i] = new TransitionHandler();
                m_transitionsTo[i]   = new TransitionHandler();
                for (int j = 0; j < m_numStates; j++)
                {
                    if (transitionMatrix[i, j])
                    {
                        m_2DTransitions[i, j] = new TransitionHandler();
                    }
                    else
                    {
                        m_2DTransitions[i, j] = new InvalidTransitionHandler();
                    }
                }
            }

            m_universalTransition = new TransitionHandler();
        }
コード例 #2
0
ファイル: StateMachine.cs プロジェクト: sjvannTMU/Sage
        /// <summary>
        /// Commands the state machine to attempt transition to the indicated state.
        /// Returns a list of ITransitionFailureReasons. If this list is empty, the
        /// transition was successful.
        /// </summary>
        /// <param name="toWhatState">The desired new state of the State Machine.</param>
        /// <param name="userData">The user data to pass into this transition request - it will be sent out of each state change notification and state method.</param>
        /// <returns>
        /// A  list of ITransitionFailureReasons. (Empty if successful.)
        /// </returns>
        public IList DoTransition(Enum toWhatState, object userData)
        {
            Debug.Assert(m_model != null, "Did you forget to set the model on the State Machine?");
            try {
                m_transitionInProgress = true;
                m_nextState            = GetStateNumber(toWhatState);

                if (s_diagnostics)
                {
                    Trace.Write("State machine in model \"" + m_model.Name + "\" servicing request to transition ");
                    _Debug.WriteLine("from \"" + State + "\" into \"" + toWhatState + "\".");
                    StackTrace st = new StackTrace();
                    _Debug.WriteLine(st.ToString());
                }

                // TODO: Determine if this is a good policy - it prohibits self-transitions.

                if (m_nextState == m_currentState)
                {
                    return(new ArrayList());
                }

                MergedTransitionHandler mth = null;
                if (m_stateMachineStructureLocked)
                {
                    if (m_mergedTransitionHandlers == null)
                    {
                        m_mergedTransitionHandlers = new MergedTransitionHandler[m_numStates][];
                        for (int i = 0; i < m_numStates; i++)
                        {
                            m_mergedTransitionHandlers[i] = new MergedTransitionHandler[m_numStates];
                        }
                    }
                    mth = m_mergedTransitionHandlers[m_currentState][m_nextState];
                }
                if (mth == null)
                {
                    TransitionHandler  outbound = (TransitionHandler)m_transitionsFrom[m_currentState];
                    ITransitionHandler across   = (ITransitionHandler)m_2DTransitions[m_currentState, m_nextState];
                    TransitionHandler  inbound  = (TransitionHandler)m_transitionsTo[m_nextState];
                    mth = new MergedTransitionHandler(outbound, (TransitionHandler)across, inbound, (TransitionHandler)m_universalTransition);
                    if (m_stateMachineStructureLocked)
                    {
                        m_mergedTransitionHandlers[m_currentState][m_nextState] = mth;
                    }
                    if (across is InvalidTransitionHandler)
                    {
                        string reason = "Illegal State Transition requested from " + State + " to " + toWhatState;
                        SimpleTransitionFailureReason stfr = new SimpleTransitionFailureReason(reason, this);
                        throw new TransitionFailureException(stfr);
                    }
                }

                if (s_diagnostics)
                {
                    _Debug.WriteLine(mth.Dump());
                }
                IList failureReasons = mth.DoPrepare(m_model, userData);
                if (failureReasons.Count != 0)
                {
                    mth.DoRollback(m_model, userData, failureReasons);
                    return(failureReasons);
                }

                mth.DoCommit(m_model, userData);

                if (s_diagnostics)
                {
                    _Debug.WriteLine("Exiting " + State);
                }
                m_currentState = m_nextState;
                TransitionCompletedSuccessfully?.Invoke(m_model, userData);
                if (s_diagnostics)
                {
                    _Debug.WriteLine("Entering " + State);
                }

                m_stateMethods[m_currentState]?.Invoke(m_model, userData);

                // After running the state method, see if there are any follow-on states to be processed.
                if (m_followOnStates == null || m_followOnStates[m_currentState] == null || m_followOnStates[m_currentState].Equals(State))
                {
                    return(null);
                }
                else
                {
                    return(DoTransition(m_followOnStates[m_currentState], userData));
                }
            } finally {
                if (s_diagnostics)
                {
                    _Debug.WriteLine("Coming to a rest in state " + State);
                }
                m_transitionInProgress = false;
                m_nextState            = m_currentState;
            }
        }
コード例 #3
0
 protected TransitionBase()
 {
     _handler = DependencyService.Get <ITransitionProvider>()?.Resolve(GetType());
 }