How to get current state from bbv.Common.StateMachine (now Appccelerate.StateMachine) class?
As Daniel explained, this is by design. Let me explain why:
The state machine allows queuing of events. Therefore, asking the state machine about its current state can be misleading. It is currently in state A, but there is already an event queued that will get it to state B.
Furthermore, I consider it to be bad design, to couple the state machine internal states (the ones you use in your state machine definition) directly with state machine external states (the ones you want to persist in the database). If you couple these two directly, you lose the ability to refactor the state machine internally without effecting the outside (in your case the database). I frequently encounter the scenario in which I have to split a state A, into A1 and A2 because I have to attach different actions to them, but nonetheless they still represented the same state to the environment. Therefore, I strongly advise you to separate the internal and external states, either as you wrote with ExecuteOnEntry() or by providing a mapping and using an extension. This is an extension that will get you the current state:
public class CurrentStateExtension : ExtensionBase<State, Event>
{
public State CurrentState { get; private set; }
public override void SwitchedState(
IStateMachineInformation<State, Event> stateMachine,
IState<State, Event> oldState,
IState<State, Event> newState)
{
this.CurrentState = newState.Id;
}
}
You can add the extension to the state machine in this way:
currentStateExtension = new CurrentStateExtension();
machine.AddExtension(currentStateExtension);
Of course you can use this extension directly to get access to the current state, too. To make it even simpler, let the class that defines the state machine implement the extension and pass itself as an extension. Let you get rid of the extra class.
A last note: when you ask questions about bbv.Common (or Appccelerate as it is called now) in the google group at https://groups.google.com/forum/?fromgroups#!forum/appccelerate, it's easier for me to find the question and answer it ;-)
This is by design. We consider querying the state of the state machine as design smell. But of course there are exception cases. You have the following two options:
- Use the
ExecuteOnEntry
methods to save the state of the order. This reflects the way to go because you don't wan't to leak the states of the statemachine into your business logic. - Write your own state machine decorator which uses internally
StateMachine<TState, TEvent>
. This exposes the state.
Daniel