Skip to content

Changing States

Scott C edited this page Sep 15, 2019 · 26 revisions

State transitions are defined when configuring states. For each state, you define the conditions under which the context should move to another state. Final states will not define any state transitions since, by definition, there won't be any state transitions from final states.

Basic state transitions

As an example, let's see how to transition a sale from the Open state to the Complete state when a customer pays

stateMachine.ConfigureState(SaleState.Open)
  .AddTransition(trigger: SaleEvent.Pay, toState: SaleState.Complete);
  • stateMachine.ConfigureState(SaleState.Open) creates the Open state and returns an IStateConfiguration.
  • IStateConfiguration.AddTransition(trigger: SaleEvent.Pay, toState: SaleState.Complete) tells the state machine to transition the sale to the toState (SaleState.Complete) when the trigger (SaleEvent.Pay) is fired.

Conditional state transitions

In many cases you'll need to check some condition before allowing the state to change. AddTransition includes a condition parameter that takes a function returning a Boolean value for this purpose. To demonstrate, let's add a condition to the previous transition that verifies the sale's balance is 0 before allowing it to move to the Complete state.

.AddTransition(trigger: SaleEvent.Pay, toState: SaleState.Complete, condition: sale.Balance == 0);

Optional parameters

AddTransition, as well as similar methods used to add more complex transitions (see below), include a couple some optional parameters.

name is any name you want to assign to a state transition. The name is included with the StateTransitionResult that's returned from StateMachine.FireTrigger and in the StateMachine.RegisterOnTransitionedAction action. Knowing this can be important when there are multiple transitions that lead to the same state.

priority determines the order in which transitions should be evaluated when FireTrigger is called. Priority isn't required because the transition conditions should all be mutually exclusive, but it's available as a safety net since NStateManager evaluates the transitions sequentially and stops when the first one is successful. You may also be able to prioritize your transitions to increase performance if you give the most likely transitions a lower priority and the most expensive transitions a higher priority.

Automatic state transitions

*** COMING SOON: There are a couple of missing pieces here before it'll be ready for prime time so consider all the information in this section a preview. ***

The key to these scenarios is that you need to change states without a trigger outside of the state machine. Some examples:

  1. After landing on a state, you determine the state isn't required so you need to move on to the next state.
  2. After entering a state and executing an action, you need to move to a new state when the action is complete.

The new state can be advancing to a new state or falling back to the state you were in before the temporary state.

Automatic state forward

TODO

Automatic state fallback

TODO

Dynamic transitions

In some scenarios, you may not know the state you need to transition to until run time. For instance, when a customer pays with a credit card, we may go into a PaymentProcessing state but we may not know the next state until we get the response from the credit card processor. If the payment succeeds, we could go to a Paid status, but if processing fails we might go to a PaymentFailed status.

AddDynamicTransition and AddAutoDynamicTransition are used to define dynamic transitions. Each of these requires a function that returns the state to transition to.