Posts Tagged many-to-many
Creating a dynamic state machine with C# and NHibernate
Posted by Patrik Löwendahl in Architecture, Code Design on September 14, 2009
In my last post (An architecture dilemma: Workflow Foundation or a hand rolled state machine?) I talked about the discussion around an architectural choice. The conclusion of that discussion was to hand-roll a dynamic state machine. This post is the first part of 3 explaining the solution we used. In this part we’ll focus on the state machine, in the following two parts we’ll be adding business rules to each state and utilizing a couple of tricks from NHibernate to make those rules rich.
If you are uncertain what the state machine pattern looks like, there is some information here: http://msdn.microsoft.com/en-us/magazine/cc301852.aspx . For the rest of this post I will assume that you got a basic understanding of it.
The requirements for our state machine was that users should be able to add their own states and tight them into the state machine. They should also be able to define the flow, designing the structure of which states can transition to each other.
The basic state machine looks something like this:
Since we need to be more dynamic then this our model turned out more like this instead:
In this model we are using composition instead of inheritance to build our state machine. The list “AllowedTransitions” contains a list of states that is allowed to transition to from the current one.
The method “CanBeChangedInto” takes a state object and compares it to the list of states and decides if the transition is allowed. For our scenario this comparison is done by implementing IEquatable and overriding the appropriate operators (==, !=).
This is defined on a template kind of entity, there will be “instances” made out of this template where all attributes are copied onto the instance.
The implementation of the ChangeStateTo method on the template is fairly simple:
Template: public void ChangeStateTo(State newState) { if (State.CanBeChangedInTo(newState)) State = newState; else throw new InvalidStateTransitionException(); } State: public bool CanBeChangedInTo(State state) { return AllowedTransitions.Contains(state); }
Simple but yet very powerful and allows for the kind of dynamic state transitions our scenario requires.
Adding state transitions is easy as well, since the AllowedTransitions list holds
Our project uses NHibernate as a persistence engine and to persist our dynamic state we use a many to many bag mapped in xml:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="" namespace=""> <class name="State" table="States"> <id name="Id" type="int"> <generator class="native" /> id> <property name="Name" length="255" not-null="true" /> <bag name="AllowedTransitions" table="AllowedStateTransitions"> <key column="FromState_Id" /> <many-to-many column="ToState_Id" class="State" /> bag> class> hibernate-mapping>
Between NHibernate many-to-many mapping and the design of the state transition list it’s easy to start building an application upon this. We are not done yet though. Every state needs more transition rules then just “AllowedTransitions”. The next post will tackle that requirement.