Creating a State Machine in Code

Lots of people create state machines.  There are many examples on the web of people who are building class libraries to make it easy to create a state machine.  These people typically don’t need (or want) to use a workflow designer or see a state diagram they simply want to write a state machine in code.

What if you could create a Windows Workflow Foundation State Machine in code?

Yes, you can create a WF4 state machine in code today.  However, if you have ever tried to create any workflow in code you find our right away that it can be a bit tricky.  You have to learn quite a bit about WF4 concepts like InArgument<T>, Variable<T>, ArgumentReference, VariableReference, VisualBasicValue etc.

The more we thought about this space the more we realized that a developer who simply wants to write code and does not need to support a workflow designer experience probably doesn’t need to use any of these things.

The idea is really very simple.  Make it possible for a developer to implement a state machine workflow using familiar language concepts like Task<T>, Action<T> or Func<T> with a simple fluent interface for creating the workflow.

Under the covers the API would construct a workflow that is run by Windows Workflow Foundation so it can take advantage of tracking, persistence and even leverage existing activities if you want to – but you don’t have to do any of these things.

I’ve written enough of a prototype to know that this can be done.  Now I want to get your input.  After all, I could spend a lot of time building something that nobody cares about.  I don’t want to over engineer this thing and I want to get it simple enough so that someone with absolutely no WF experience could in less than an hour create and run a simple state machine.

Prototype Code

This prototype code is creating the state machine activity that you build in exercise 1 of the Introduction to State Machine Hands on Lab.  For a prototype I wanted to see how it would feel to use an alternate code based API with no workflow concepts at all.

Download the prototype code here

 private StateMachine<AtmState, AtmTrigger> CreateStateMachine()
 {
     // Fluent interface for declaring the state machine
     // Enums define the states and transitions
     this.atmStateMachine = new StateMachine<AtmState, AtmTrigger> { DisplayName = "ATM StateMachine" };
  
     // Use an indexer to refer to the state you want
     // Non workflow developers can use lambda expressions or Action to provide implementation - no need to learn WF
     // AutoTrigger is a null transition
     this.atmStateMachine[AtmState.Initialized]
         .Entry(this.Prompt, Activities.Prompts.PleaseWait)
         .Exit(this.ClearView)
         .AutoTrigger(AtmState.InsertCard);
  
     // When defines a transition that is implemented with a bookmark
     this.atmStateMachine[AtmState.InsertCard]
         .Entry(this.Prompt, Activities.Prompts.InsertCard)
         .When(AtmTrigger.PowerOff, AtmState.PowerOff);
  
     this.atmStateMachine[AtmState.PowerOff]
         .Entry(this.ClearView);
  
     return this.atmStateMachine;
 }

How you can help

Take a look at the Microsoft.Activities.StateMachine project page and leave a comment or vote for this issue and leave a comment to tell us why you care about this.

Happy Coding!

Ron Jacobs

https://blogs.msdn.com/rjacobs

Twitter: @ronljacobs https://twitter.com/ronljacobs

Comments

  • Anonymous
    June 08, 2011
    The comment has been removed

  • Anonymous
    June 15, 2011
    Ron, I definately want to take a depp look at what you have done, it can address many needs. On the other hand (isnt there always another hand??) alot of times I use a workflow (sequential or state machine) simply because I want (almost "need") the visualization and the ability for someone else to "tweak" the workflow (especially in the face of eventual gchanging requirements. The visual aspect is (for these cases) a key driving aspect of selecting WF in the first place. What I would REALLY love to see is a way to create the WF in code, but in a manner that could be "run through a process" that allowed it to be visualized and have the editing capabilities of the "GUI". David

  • Anonymous
    June 15, 2011
    As you can see in the source unit tests, you can export the code created workflow to XAML.  However right now I'm using things that cannot be visualized in the designer. Then once you open it in the designer and make changes there is no way to get it back to the code format.  There are many challenges to getting round tripping to work correctly.  For now I'm just focused on a great code based experience.

  • Anonymous
    June 29, 2011
    A lot of appeal over the UI-centric approach. What are the major hurdles to round-tripping between the two methods? Can/could we hope to see improvements for David Corbin's scenario?