C# – Dependency injection with Finite State Machines and the Interface Segregation Principle

cdependency-injectionfinite-state machineobject-oriented-design

I am trying to figure out what is the best way to setup a FSM and also keep my interfaces clean and use an IOC container to use DI.

Let's just visit the Head First design pattern textbook example of the gumball machine.

interface IState
{
    InsertQuarter();
    EjectQuarter();
    TurnCrank();
    Dispense();
}

Is the best practice to just thrown an exception for an invalid state? Why add the state if it's not even applicable? I guess that is the portion where I am confused. I could see this simple example getting more complex.

My other related question is, how do I perform DI to these states? Should a state machine and states should be registered in my IOC container? Let's suppose I have an Order Service and an Inventory Service that have a dependency on a StageOrderState. What might this object model look like? I'm having a hard time digesting how to actually inject the dependencies in to these states. My guess is that I could register the states and pass the container around to the states.

Best Answer

It seems to me that you want to genericize the Head First example, so that it can accept an arbitrary collection of actions.

In C# you can have first-class functions, which means that you can pass functions to your finite state machine and have it maintain those functions in a list. Something like:

interface IState
{
    void AddStep(Action<T> action);
}

And then just pass your function to the AddStep method for insertion into the list by the state machine.

public class StateMachine : IState
{
    List<Action<T>> actions;

    public void AddStep(Action<T> action)
    {
        actions.Add(action);
    }
}

Then you just add your actions.

var machine = new StateMachine();
machine.AddStep(x => Console.WriteLine(x.ToString()));