Melodie Gauthier
Melodie Gauthier

Reputation: 715

State machine - embedded switch

I am working on my first asp.net mvc web application. I have a form that can be in 14 different states and depending of the current state, transition to other states are or are not possible. There is an average of 3-5 differents possible next state for each current state.

What I need to do now is trigger actions during some state transition. Depending on the initial state and the final states, some actions are trigged (emails are sent for example).

I started this by using switch statements:

switch ((int)currentState)
        {
            //Initial
            case -1:
                {
                    switch ((int)nextState)
                    {
                        //Next state: Inv. is waiting
                        case 1: 
                            {
                                //Send email to x
                                emailHelper.Send(x,msg)
                                //Send email to Y
                                emailHelper.Send(y,anotherMsg)

                            }
                        case 2: 
                            {
                                doSomethingelse()
                            }
                            break;
                    }
                    break;
                }
            //Inv is waiting
            case 1:
                {
                    switch ((int)nextState)
                    {
                        ...
                    }
                }
  ...

I think this solution would work fine for me, but I am wondering if I could use something better..Any suggestions?

Upvotes: 0

Views: 918

Answers (3)

AlexD
AlexD

Reputation: 32576

If performance is not an issue at all, and the only thing you are interested is compact code, consider

switch(string.Format(CultureInfo.InvariantCulture, "{0} {1}", currentState, nextState))
{
    case "-1 1":
        //Send email to x
        emailHelper.Send(x,msg);
        //Send email to Y
        emailHelper.Send(y,anotherMsg);
        break;
    case "-1 2":
        doSomethingelse();
        break;
    ....
}

You could also wait for C# 7.0 and use its new form of switch statement. Something like this:

struct State
{
    int Current;
    int Next;
}

....

State s;
switch (s)
{
    case State x when (x.Current == -1 && x.Next == 1):
        ....
}

Upvotes: 2

PhillipH
PhillipH

Reputation: 6222

(pseudo code)

class StateHandler
{
    int CurrentState;
    int NextState;
    Action MyAction;

    public void Eval(int currentState, int nextState)
    {
        if(currentState == this.CurrentState && nextState == this.NextState)
        {
             this.MyAction();
        }
    }
}

Create a List and populate it with all known state transitions. Then just iterate the List and call Eval() on each item.

List<StateHandler> handlers = new List<StateHandler>();
handlers.Add(new StateHandler() 
{ 
   currentState = 0, 
   nextState = 1,  
   () => doSomeWork() 
}
handlers.Add(new StateHandler() 
{ 
   currentState = 3, 
   nextState = 4,  
   () => doSomeOtherWork() 
}

Upvotes: 1

Ken Wayne VanderLinde
Ken Wayne VanderLinde

Reputation: 19349

Perhaps you could use a data structure to store the states and transitions. For example, the state machine could be a Dictionary<int, State>, where State could be as simple as

struct State {
  Dictionary<int, Action> transitions;
}

Performing a state transition then looks like

var action = states[currentState].transitions[nextState];
action();
currentState = nextState;

Of course, this solution could be more encapsulated, and could use checks as to whether a transition exists, but this is the gist of it

Upvotes: 2

Related Questions