<?xml version="1.0"?><?xml-stylesheet type="text/xsl" href="http://www.codeplex.com/rss.xsl"?><rss version="2.0"><channel><title>SimpleStateMachine Wiki &amp; Documentation Rss Feed</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home</link><description>SimpleStateMachine Wiki Rss Description</description><item><title>Updated Wiki: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=17</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.&lt;br /&gt; &lt;br /&gt;Technology: .NET 3.5 (VS2008), C#3.0, Boo Language, Rhino DSL&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library written in C# that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;As for state persistence, you have to provide your own repository for persisting any domain objects you are using as the context for your state machine by implementing an IDomainContextRepository interface, but SimpleStateMachine will take care of invoking the appropriate persistence actions after each state transition, including ensuring that the persistence operation takes place within a transaction if you have your state machine marked as transactional. Here you can find a &lt;a href="http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active%20Record%20Persistence&amp;amp;referringTitle=Home"&gt;tutorial&lt;/a&gt; on how to use Castle's Active Record for persisting to a database.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
trigger @CallDialed
trigger @HungUp
trigger @CallConnected
trigger @LeftMessage
 
trigger @PlacedOnHold:
         on_event @PlayMuzak
 
trigger @TakenOffHold
          on_event @StopMuzak
 
trigger @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt; &lt;br /&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Sun, 15 Feb 2009 04:57:16 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Home 20090215045716A</guid></item><item><title>Updated Wiki: Active Record Persistence</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active Record Persistence&amp;version=5</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;The current trunk (as of august 28, 2008) allows users to override the default file persistence storage. This is a small howto to demonstrate the use of &lt;a href="http://www.castleproject.org/activerecord/" class="externalLink"&gt;Active Record&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; to persist workflow definitions to a database.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Persistence&lt;/b&gt;&lt;br /&gt;In workflow scenario's that have longer life cycle it's wise to store the workflow state somewhere that survives system failures, reboots or other unexpected things rather then keeping it in memory. This is where the persistence services of the Simple State Machine project comes in.&lt;br /&gt; &lt;br /&gt;When saving a workflow we need to store enough information so that we can later recreate a statemachine and continue to run as if nothing ever happened.&lt;br /&gt; &lt;br /&gt;With that in mind we can determine that there are a couple of things that need to be stored;&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;the workflow identity&lt;/li&gt;&lt;li&gt;it's state&lt;/li&gt;&lt;li&gt;the machine definition&lt;/li&gt;&lt;li&gt;the link with the application domain (the domain content)&lt;/li&gt;
&lt;/ul&gt; &lt;br /&gt;Storing the identity and the current state is not so difficult. Each statemachine contains a GUID that we can use and the current state has a name. &lt;br /&gt;The machine definition, as you probably know, is stored inside your boo files, so if we store the name of the file that was used to create the workflow we should have enough information to restart the machine later.&lt;br /&gt; &lt;br /&gt;The domain context is the part that reflects the state of the workflow inside your application domain. Each time we ask the Workflow Service (WS) to handle an event it can also update the state in your domain model. We'll look at this link later on.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;The case&lt;/b&gt;&lt;br /&gt;In this howto we will be building a workflow service that can handle an account opening request at our company. Customers that apply for an account are required to send in a signed contact and make a deposit of 100 Euro to our bank account. &lt;br /&gt; &lt;br /&gt;When these two requirements are met an account manager can activate the account and the customer can start using the provided services. A final requirement is that account opening requests can be denied as long as they have not been accepted.&lt;br /&gt; &lt;br /&gt;This gives us the following workflow definition:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
workflow &amp;quot;Account Opening Request workflow&amp;quot;
 
#Event Definitions
#--------------------------------------------------------
trigger @AccountRequestSubmitted
trigger @AccountRequestDenied
trigger @AccountRequestAccepted
trigger @SignedContractReceived
trigger @DepositReceived
trigger @AccountClosed
 
#State &amp;amp; Transition Definitions
#--------------------------------------------------------
state @AccountRequestPending:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @SignedContractReceived		&amp;gt;&amp;gt; @AwaitingDeposit
 
state @AwaitingDeposit:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @DepositReceived			&amp;gt;&amp;gt; @AwaitingAccountActivation
 
state @AwaitingAccountActivation:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @AccountRequestAccepted		&amp;gt;&amp;gt; @AccountActivated
 
state @AccountActivated:
	when @AccountClosed			&amp;gt;&amp;gt; @AccountClosed
 
state @AccountClosed
state @AccountRequestDenied
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;The domain model&lt;/b&gt;&lt;br /&gt;Our domain model currently only contains one account class that represents the account opening request for the customer. As you can see we are using ActiveRecord as a persistence engine. The ModelBase class is nothing more the an abstract class that sits on top of our domain model that provides an Id.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class Account : ModelBase
{
	private string _customerName;
	private AccountState _accountState;
 
	[Property]
	public string CustomerName
	{
		get { return _customerName; }
		set { _customerName = value; }
	}
 
	[Property]
	public AccountState AccountState
	{
		get { return _accountState; }
		set { _accountState = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;Active record binding&lt;/b&gt;&lt;br /&gt;Out of the box Simple State Machine (SSM) provides support for saving workflow definitions (WFD) to disk using the .Net XmlSerializer class. When storing a WFD in a database we need a different structure. So the first thing we need to do is to create an Active Record entity that can store such a WFD. &lt;br /&gt; &lt;br /&gt;This is done by implementing the IWorkflowEntity interface and it looks like this:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class ARWorkflowEntity : IWorkflowEntity {
	private Guid _workflowId;
	private string _machineConfiguration;
	private string _currentState;
	private string _domainContextTypeDescription;
	private object _domainContextId;
	private string _domainContextStatusProperty;
 
	/// &amp;lt;summary&amp;gt;
	/// Get or set the Id of this entity
	/// &amp;lt;/summary&amp;gt;
	[PrimaryKey(Generator = PrimaryKeyType.Assigned)]
	public Guid Id {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	public Guid WorkflowId {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	[Property]
	public string MachineConfiguration {
		get { return _machineConfiguration; }
		set { _machineConfiguration = value; }
	}
 
	[Property]
	public string CurrentState {
		get { return _currentState; }
		set { _currentState = value; }
	}
 
	[Property]
	public string DomainContextTypeDescription {
		get { return _domainContextTypeDescription; }
		set { _domainContextTypeDescription = value; }
	}
 
	public object DomainContextId {
		get { return _domainContextId; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public int PersistedDomainContextID {
		get { return _domainContextId is int ? (int)_domainContextId : 0; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public string DomainContextStatusProperty {
		get { return _domainContextStatusProperty; }
		set { _domainContextStatusProperty = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt;Since Active Record doesn't know how to persist the anonymous DomainContextId property, we use a little trick to unbox it via the PersistedDomainContextID property.&lt;br /&gt; &lt;br /&gt;The saving and loading of WFD is accomplished via the IWorkflowPersister interface. So the next thing is to implement a WorkflowPersister that uses Active Record.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Active record workflow persister
/// &amp;lt;/summary&amp;gt;
public class ARWorkflowPersister : IWorkflowPersister
{
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Save(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.CreateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Updates the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Update(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified workflow id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity Load(Guid workflowId)
	{
		return (IWorkflowEntity) ActiveRecordMediator.FindByPrimaryKey(typeof(ARWorkflowEntity), workflowId, true);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Completes the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Complete(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Creates the empty workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity CreateEmptyWorkflowEntity(Guid workflowId)
	{
		return new ARWorkflowEntity { WorkflowId = workflowId };
	}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;Domain binding&lt;/b&gt;&lt;br /&gt;We are almost ready to see our workflow persisting service in action. There is one last binding that we need to realize and that's the link between our application domain and the workflow. As you'll remember from the start of this article, we have a class called Account that we want to associate with a running workflow. This can be accomplished by passing an Account instance when we start a workflow.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
		
// this is where we pass the account instance to make a link between the workflow and the account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;The binding between the workflow instance and the domain entity is kept by the DomainContextRepository. Classes that implement such an interface must be able to create a string that allows us to identify the domain object that the workflow is linked to. We need this because the Workflow Service has no idea what kind object you are passing as a reference our how you would like to restore it in the case of a new event that needs to be handled. In this example we'll be using the Type name and the object's namespace.&lt;br /&gt; &lt;br /&gt;This is the code for the Active Record DomainContextRepository:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
public class ARDomainContextRepository : IDomainContextRepository {
	/// &amp;lt;summary&amp;gt;
	/// Gets the id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object GetId(object instance) {
		return ((ModelBase)instance).Id;
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Gets the type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public string GetTypeDescription(object instance) {
		var type = instance.GetType();
		return string.Format(&amp;quot;{0}, {1}&amp;quot;, type.FullName, type.Assembly.GetName().Name);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;typeDescription&amp;quot;&amp;gt;The type description.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&amp;quot;id&amp;quot;&amp;gt;The id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object Load(string typeDescription, object id) {
		var type = Type.GetType(typeDescription, true);
		return ActiveRecordMediator.FindByPrimaryKey(type, id);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified instance.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	public void Save(object instance) {
		ActiveRecordMediator.SaveAndFlush(instance);
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;The application&lt;/b&gt;&lt;br /&gt;Now that we've implemented all our bindings we can start writing a sample application that create a new account and starts the workflow. You can step through it and keep an eye on your database to see it updating the values. &lt;br /&gt; &lt;br /&gt;Here is our sample application:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
 
// then we start the workflow for the new account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
 
// we received a signed contact and would like to update the workflow state.
machineContext.HandleEvent(AccountEvent.SignedContractReceived);
 
// the next state should be that we are waiting for the deposit
Assert.That(myAccount.AccountState, Is.EqualTo(AccountState.AwaitingDeposit));
 
// this should also be stored in the database
var entity = (ARWorkflowEntity) ActiveRecordMediator.FindFirst(typeof (ARWorkflowEntity));
Assert.That(entity.CurrentState, Is.EqualTo(Convert.ToString(AccountState.AwaitingDeposit)));
 
// walk through the rest of the workflow, you can place breakpoints on these line to see the WFD updating in the DB.
machineContext.HandleEvent(AccountEvent.DepositReceived);
machineContext.HandleEvent(AccountEvent.AccountRequestAccepted);
machineContext.HandleEvent(AccountEvent.AccountClosed);
 
// and it should be completed here
Assert.That(machineContext.IsComplete);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;Attached is a zip file that contains a Visual Studio solution with all the code, libraries and the sample application as a unit test so you can see it running. Download it &lt;a href="javascript:window.location.href='http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=SimpleStateMachine&amp;amp;DownloadId=42423';"&gt;here&lt;/a&gt;.&lt;br /&gt; &lt;br /&gt;As a final note:&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;Don't forget to create a database named '&lt;b&gt;ActiveRecordWorkflowSample&lt;/b&gt;'. &lt;/li&gt;&lt;li&gt;It assumes a local copy of SQLExpress, check the setup function for connection details.&lt;/li&gt;&lt;li&gt;The sample application is licensed under the Apache License, Version 2.0 so you're free to use it as you like.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>ernstnaezer</author><pubDate>Thu, 28 Aug 2008 13:35:09 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Active Record Persistence 20080828013509P</guid></item><item><title>Updated Wiki: Active Record Persistence</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active Record Persistence&amp;version=4</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;The current trunk (as of aug. 28) allows users to override the default file persistence storage. This is a small howto to demonstrate the use of &lt;a href="http://www.castleproject.org/activerecord/" class="externalLink"&gt;Active Record&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; to persist workflow definitions to a database.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Persistence&lt;/b&gt;&lt;br /&gt;In workflow scenario's that have longer life cycle it's wise to store the workflow state somewhere that survives system failures, reboots or other unexpected things rather then keeping it in memory. This is where the persistence services of the Simple State Machine project come in.&lt;br /&gt; &lt;br /&gt;When saving a workflow we need to store enough information so that we can later recreate a statemachine and continue to run as if nothing ever happened.&lt;br /&gt; &lt;br /&gt;With that in mind we can determine that there are a couple of things that need to be stored;&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;the workflow identity,&lt;/li&gt;&lt;li&gt;it's state&lt;/li&gt;&lt;li&gt;the machine definition&lt;/li&gt;&lt;li&gt;the link with the application domain (the domain content)&lt;/li&gt;
&lt;/ul&gt; &lt;br /&gt;Storing the identity and the current state is not so difficult. Each statemachine contains a GUID that we can use and the current state has a name. &lt;br /&gt;The machine definition, as you probably know, is stored inside your boo files, so if we store the name of the file that was used to create the workflow we should have enough information to restart the machine later.&lt;br /&gt; &lt;br /&gt;The domain context is the part that reflects the state of the workflow inside your application domain. Each time we ask the Workflow Service (WS) to handle an event it can also update the state in your domain model. We'll look at this link later on.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;The case&lt;/b&gt;&lt;br /&gt;In this howto we will be building a workflow service that can handle an account opening request at our company. Customers that apply for an account are required to send in a signed contact and make a deposit of 100 Euro to our bank account. &lt;br /&gt; &lt;br /&gt;When these two requirements are met an account manager can activate the account and the customer can start using the provided services. A final requirement is that account opening requests can be denied as long as they have not been accepted.&lt;br /&gt; &lt;br /&gt;This gives us the following workflow definition:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
workflow &amp;quot;Account Opening Request workflow&amp;quot;
 
#Event Definitions
#--------------------------------------------------------
trigger @AccountRequestSubmitted
trigger @AccountRequestDenied
trigger @AccountRequestAccepted
trigger @SignedContractReceived
trigger @DepositReceived
trigger @AccountClosed
 
#State &amp;amp; Transition Definitions
#--------------------------------------------------------
state @AccountRequestPending:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @SignedContractReceived		&amp;gt;&amp;gt; @AwaitingDeposit
 
state @AwaitingDeposit:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @DepositReceived			&amp;gt;&amp;gt; @AwaitingAccountActivation
 
state @AwaitingAccountActivation:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @AccountRequestAccepted		&amp;gt;&amp;gt; @AccountActivated
 
state @AccountActivated:
	when @AccountClosed			&amp;gt;&amp;gt; @AccountClosed
 
state @AccountClosed
state @AccountRequestDenied
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;The domain model&lt;/b&gt;&lt;br /&gt;Our domain model currently only contains one account class that represents the account opening request for the customer. As you can see we are using ActiveRecord as a persistence engine. The ModelBase class is nothing more the an abstract class that sits on top of our domain model that provides an Id.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class Account : ModelBase
{
	private string _customerName;
	private AccountState _accountState;
 
	[Property]
	public string CustomerName
	{
		get { return _customerName; }
		set { _customerName = value; }
	}
 
	[Property]
	public AccountState AccountState
	{
		get { return _accountState; }
		set { _accountState = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;Active record binding&lt;/b&gt;&lt;br /&gt;Out of the box Simple State Machine (SSM) provides support for saving workflow definitions (WFD) to disk using the .Net XmlSerializer class. When storing a WFD in a database we need a different structure. So the first thing we need to do is to create an Active Record entity that can store such a WFD. &lt;br /&gt; &lt;br /&gt;This is done by implementing the IWorkflowEntity interface and it looks like this:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class ARWorkflowEntity : IWorkflowEntity {
	private Guid _workflowId;
	private string _machineConfiguration;
	private string _currentState;
	private string _domainContextTypeDescription;
	private object _domainContextId;
	private string _domainContextStatusProperty;
 
	/// &amp;lt;summary&amp;gt;
	/// Get or set the Id of this entity
	/// &amp;lt;/summary&amp;gt;
	[PrimaryKey(Generator = PrimaryKeyType.Assigned)]
	public Guid Id {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	public Guid WorkflowId {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	[Property]
	public string MachineConfiguration {
		get { return _machineConfiguration; }
		set { _machineConfiguration = value; }
	}
 
	[Property]
	public string CurrentState {
		get { return _currentState; }
		set { _currentState = value; }
	}
 
	[Property]
	public string DomainContextTypeDescription {
		get { return _domainContextTypeDescription; }
		set { _domainContextTypeDescription = value; }
	}
 
	public object DomainContextId {
		get { return _domainContextId; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public int PersistedDomainContextID {
		get { return _domainContextId is int ? (int)_domainContextId : 0; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public string DomainContextStatusProperty {
		get { return _domainContextStatusProperty; }
		set { _domainContextStatusProperty = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt;Since Active Record doesn't know how to persist the anonymous DomainContextId property we use a little trick to unbox it via the PersistedDomainContextID property.&lt;br /&gt; &lt;br /&gt;The saving and loading of WFD is accomplished via the IWorkflowPersister interface. So the next thing is to implement a WorkflowPersister that uses Active Record.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Active record workflow persister
/// &amp;lt;/summary&amp;gt;
public class ARWorkflowPersister : IWorkflowPersister
{
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Save(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.CreateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Updates the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Update(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified workflow id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity Load(Guid workflowId)
	{
		return (IWorkflowEntity) ActiveRecordMediator.FindByPrimaryKey(typeof(ARWorkflowEntity), workflowId, true);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Completes the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Complete(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Creates the empty workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity CreateEmptyWorkflowEntity(Guid workflowId)
	{
		return new ARWorkflowEntity { WorkflowId = workflowId };
	}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;Domain binding&lt;/b&gt;&lt;br /&gt;We are almost ready to see our workflow persisting service in action. There is one last binding that we need to realize and that's the link between our application domain and the workflow. As you'll remember from the start of this article, we have a class called Account that we want to associate with a running workflow. This can be accomplished by passing an Account instance when we start a workflow.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
		
// this is where we pass the account instance to make a link between the workflow and the account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;The binding between the workflow instance and the domain entity is kept by the DomainContextRepository. Classes that implement such an interface must be able to create a string that allows us to identify the domain object that the workflow is linked to. We need this because the Workflow Service has no idea what kind object you are passing as a reference our how you would like to restore it in the case of a new event that needs to be handled. In this example we'll be using the Type name and the object's namespace.&lt;br /&gt; &lt;br /&gt;This is the code for the Active Record DomainContextRepository:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
public class ARDomainContextRepository : IDomainContextRepository {
	/// &amp;lt;summary&amp;gt;
	/// Gets the id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object GetId(object instance) {
		return ((ModelBase)instance).Id;
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Gets the type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public string GetTypeDescription(object instance) {
		var type = instance.GetType();
		return string.Format(&amp;quot;{0}, {1}&amp;quot;, type.FullName, type.Assembly.GetName().Name);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;typeDescription&amp;quot;&amp;gt;The type description.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&amp;quot;id&amp;quot;&amp;gt;The id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object Load(string typeDescription, object id) {
		var type = Type.GetType(typeDescription, true);
		return ActiveRecordMediator.FindByPrimaryKey(type, id);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified instance.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	public void Save(object instance) {
		ActiveRecordMediator.SaveAndFlush(instance);
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;The application&lt;/b&gt;&lt;br /&gt;Now that we've implemented all our bindings we can start writing a sample application that create a new account and starts the workflow. You can step through it and keep an eye on your database to see it updating the values. &lt;br /&gt; &lt;br /&gt;Here is our sample application:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
 
// then we start the workflow for the new account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
 
// we received a signed contact and would like to update the workflow state.
machineContext.HandleEvent(AccountEvent.SignedContractReceived);
 
// the next state should be that we are waiting for the deposit
Assert.That(myAccount.AccountState, Is.EqualTo(AccountState.AwaitingDeposit));
 
// this should also be stored in the database
var entity = (ARWorkflowEntity) ActiveRecordMediator.FindFirst(typeof (ARWorkflowEntity));
Assert.That(entity.CurrentState, Is.EqualTo(Convert.ToString(AccountState.AwaitingDeposit)));
 
// walk through the rest of the workflow, you can place breakpoints on these line to see the WFD updating in the DB.
machineContext.HandleEvent(AccountEvent.DepositReceived);
machineContext.HandleEvent(AccountEvent.AccountRequestAccepted);
machineContext.HandleEvent(AccountEvent.AccountClosed);
 
// and it should be completed here
Assert.That(machineContext.IsComplete);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;Attached is a zip file that contains a Visual Studio solution with all the code, libraries and the sample application as a unit test so you can see it running. Download it &lt;a href="javascript:window.location.href='http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=SimpleStateMachine&amp;amp;DownloadId=42423';"&gt;here&lt;/a&gt;.&lt;br /&gt; &lt;br /&gt;As a final note:&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;Don't forget to create a database named '&lt;b&gt;ActiveRecordWorkflowSample&lt;/b&gt;'. &lt;/li&gt;&lt;li&gt;It assumes a local copy of SQLExpress, check the setup function for connection details.&lt;/li&gt;&lt;li&gt;The sample application is licensed under the Apache License, Version 2.0 so you're free to use it as you like.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>ernstnaezer</author><pubDate>Thu, 28 Aug 2008 13:23:08 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Active Record Persistence 20080828012308P</guid></item><item><title>Updated Wiki: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=16</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;Technology: .NET 3.5 (VS2008), C#3.0, Boo Language, Rhino DSL&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library written in C# that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;As for state persistence, you have to provide your own repository for persisting any domain objects you are using as the context for your state machine by implementing an IDomainContextRepository interface, but SimpleStateMachine will take care of invoking the appropriate persistence actions after each state transition, including ensuring that the persistence operation takes place within a transaction if you have your state machine marked as transactional. Here you can find a &lt;a href="http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active%20Record%20Persistence&amp;amp;referringTitle=Home"&gt;tutorial&lt;/a&gt; on how to use Castle's Active Record for persisting to a database.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
trigger @CallDialed
trigger @HungUp
trigger @CallConnected
trigger @LeftMessage
trigger @PlacedOnHold
trigger @TakenOffHold
trigger @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt; &lt;br /&gt;
&lt;/div&gt;</description><author>ernstnaezer</author><pubDate>Thu, 28 Aug 2008 13:21:56 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Home 20080828012156P</guid></item><item><title>Updated Wiki: Active Record Persistence</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active Record Persistence&amp;version=3</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Introduction&lt;/b&gt;&lt;br /&gt;The current trunk (as of aug. 28) allows users to override the default file persistence storage. This is a small howto to demonstrate the use of &lt;a href="http://www.castleproject.org/activerecord/" class="externalLink"&gt;Active Record&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; to persist workflow definitions to a database.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;Persistence&lt;/b&gt;&lt;br /&gt;In workflow scenario's that have longer life cycle it's wise to store the workflow state somewhere that survives system failures, reboots or other unexpected things rather then keeping it in memory. This is where the persistence services of the Simple State Machine project come in.&lt;br /&gt; &lt;br /&gt;When saving a workflow we need to store enough information so that we can later recreate a statemachine and continue to run as if nothing ever happened.&lt;br /&gt; &lt;br /&gt;With that in mind we can determine that there are a couple of things that need to be stored;&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;the workflow identity,&lt;/li&gt;&lt;li&gt;it's state&lt;/li&gt;&lt;li&gt;the machine definition&lt;/li&gt;&lt;li&gt;the link with the application domain (the domain content)&lt;/li&gt;
&lt;/ul&gt; &lt;br /&gt;Storing the identity and the current state is not so difficult. Each statemachine contains a GUID that we can use and the current state has a name. &lt;br /&gt;The machine definition, as you probably know, is stored inside your boo files, so if we store the name of the file that was used to create the workflow we should have enough information to restart the machine later.&lt;br /&gt; &lt;br /&gt;The domain context is the part that reflects the state of the workflow inside your application domain. Each time we ask the Workflow Service (WS) to handle an event it can also update the state in your domain model. We'll look at this link later on.&lt;br /&gt; &lt;br /&gt;&lt;b&gt;The case&lt;/b&gt;&lt;br /&gt;In this howto we will be building a workflow service that can handle an account opening request at our company. Customers that apply for an account are required to send in a signed contact and make a deposit of 100 Euro to our bank account. &lt;br /&gt; &lt;br /&gt;When these two requirements are met an account manager can activate the account and the customer can start using the provided services. A final requirement is that account opening requests can be denied as long as they have not been accepted.&lt;br /&gt; &lt;br /&gt;This gives us the following workflow definition:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
workflow &amp;quot;Account Opening Request workflow&amp;quot;
 
#Event Definitions
#--------------------------------------------------------
trigger @AccountRequestSubmitted
trigger @AccountRequestDenied
trigger @AccountRequestAccepted
trigger @SignedContractReceived
trigger @DepositReceived
trigger @AccountClosed
 
#State &amp;amp; Transition Definitions
#--------------------------------------------------------
state @AccountRequestPending:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @SignedContractReceived		&amp;gt;&amp;gt; @AwaitingDeposit
 
state @AwaitingDeposit:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @DepositReceived			&amp;gt;&amp;gt; @AwaitingAccountActivation
 
state @AwaitingAccountActivation:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @AccountRequestAccepted	&amp;gt;&amp;gt; @AccountActivated
 
state @AccountActivated:
	when @AccountClosed			&amp;gt;&amp;gt; @AccountClosed
 
state @AccountClosed
state @AccountRequestDenied
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;The domain model&lt;/b&gt;&lt;br /&gt;Our domain model currently only contains one account class that represents the account opening request for the customer. As you can see we are using ActiveRecord as a persistence engine. The ModelBase class is nothing more the an abstract class that sits on top of our domain model that provides an Id.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class Account : ModelBase
{
	private string _customerName;
	private AccountState _accountState;
 
	[Property]
	public string CustomerName
	{
		get { return _customerName; }
		set { _customerName = value; }
	}
 
	[Property]
	public AccountState AccountState
	{
		get { return _accountState; }
		set { _accountState = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;Active record binding&lt;/b&gt;&lt;br /&gt;Out of the box Simple State Machine (SSM) provides support for saving workflow definitions (WFD) to disk using the .Net XmlSerializer class. When storing a WFD in a database we need a different structure. So the first thing we need to do is to create an Active Record entity that can store such a WFD. &lt;br /&gt; &lt;br /&gt;This is done by implementing the IWorkflowEntity interface and it looks like this:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class ARWorkflowEntity : IWorkflowEntity {
	private Guid _workflowId;
	private string _machineConfiguration;
	private string _currentState;
	private string _domainContextTypeDescription;
	private object _domainContextId;
	private string _domainContextStatusProperty;
 
	/// &amp;lt;summary&amp;gt;
	/// Get or set the Id of this entity
	/// &amp;lt;/summary&amp;gt;
	[PrimaryKey(Generator = PrimaryKeyType.Assigned)]
	public Guid Id {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	public Guid WorkflowId {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	[Property]
	public string MachineConfiguration {
		get { return _machineConfiguration; }
		set { _machineConfiguration = value; }
	}
 
	[Property]
	public string CurrentState {
		get { return _currentState; }
		set { _currentState = value; }
	}
 
	[Property]
	public string DomainContextTypeDescription {
		get { return _domainContextTypeDescription; }
		set { _domainContextTypeDescription = value; }
	}
 
	public object DomainContextId {
		get { return _domainContextId; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public int PersistedDomainContextID {
		get { return _domainContextId is int ? (int)_domainContextId : 0; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public string DomainContextStatusProperty {
		get { return _domainContextStatusProperty; }
		set { _domainContextStatusProperty = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt;Since Active Record doesn't know how to persist the anonymous DomainContextId property we use a little trick to unbox it via the PersistedDomainContextID property.&lt;br /&gt; &lt;br /&gt;The saving and loading of WFD is accomplished via the IWorkflowPersister interface. So the next thing is to implement a WorkflowPersister that uses Active Record.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Active record workflow persister
/// &amp;lt;/summary&amp;gt;
public class ARWorkflowPersister : IWorkflowPersister
{
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Save(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.CreateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Updates the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Update(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified workflow id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity Load(Guid workflowId)
	{
		return (IWorkflowEntity) ActiveRecordMediator.FindByPrimaryKey(typeof(ARWorkflowEntity), workflowId, true);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Completes the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Complete(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Creates the empty workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity CreateEmptyWorkflowEntity(Guid workflowId)
	{
		return new ARWorkflowEntity { WorkflowId = workflowId };
	}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;Domain binding&lt;/b&gt;&lt;br /&gt;We are almost ready to see our workflow persisting service in action. There is one last binding that we need to realize and that's the link between our application domain and the workflow. As you'll remember from the start of this article, we have a class called Account that we want to associate with a running workflow. This can be accomplished by passing an Account instance when we start a workflow.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
		
// this is where we pass the account instance to make a link between the workflow and the account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;The binding between the workflow instance and the domain entity is kept by the DomainContextRepository. Classes that implement such an interface must be able to create a string that allows us to identify the domain object that the workflow is linked to. We need this because the Workflow Service has no idea what kind object you are passing as a reference our how you would like to restore it in the case of a new event that needs to be handled. In this example we'll be using the Type name and the object's namespace.&lt;br /&gt; &lt;br /&gt;This is the code for the Active Record DomainContextRepository:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
public class ARDomainContextRepository : IDomainContextRepository {
	/// &amp;lt;summary&amp;gt;
	/// Gets the id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object GetId(object instance) {
		return ((ModelBase)instance).Id;
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Gets the type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public string GetTypeDescription(object instance) {
		var type = instance.GetType();
		return string.Format(&amp;quot;{0}, {1}&amp;quot;, type.FullName, type.Assembly.GetName().Name);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;typeDescription&amp;quot;&amp;gt;The type description.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&amp;quot;id&amp;quot;&amp;gt;The id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object Load(string typeDescription, object id) {
		var type = Type.GetType(typeDescription, true);
		return ActiveRecordMediator.FindByPrimaryKey(type, id);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified instance.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	public void Save(object instance) {
		ActiveRecordMediator.SaveAndFlush(instance);
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;b&gt;The application&lt;/b&gt;&lt;br /&gt;Now that we've implemented all our bindings we can start writing a sample application that create a new account and starts the workflow. You can step through it and keep an eye on your database to see it updating the values. &lt;br /&gt; &lt;br /&gt;Here is our sample application:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
 
// then we start the workflow for the new account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
 
// we received a signed contact and would like to update the workflow state.
machineContext.HandleEvent(AccountEvent.SignedContractReceived);
 
// the next state should be that we are waiting for the deposit
Assert.That(myAccount.AccountState, Is.EqualTo(AccountState.AwaitingDeposit));
 
// this should also be stored in the database
var entity = (ARWorkflowEntity) ActiveRecordMediator.FindFirst(typeof (ARWorkflowEntity));
Assert.That(entity.CurrentState, Is.EqualTo(Convert.ToString(AccountState.AwaitingDeposit)));
 
// walk through the rest of the workflow, you can place breakpoints on these line to see the WFD updating in the DB.
machineContext.HandleEvent(AccountEvent.DepositReceived);
machineContext.HandleEvent(AccountEvent.AccountRequestAccepted);
machineContext.HandleEvent(AccountEvent.AccountClosed);
 
// and it should be completed here
Assert.That(machineContext.IsComplete);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;Attached is a zip file that contains a Visual Studio solution with all the code, libraries and the sample application as a unit test so you can see it running. Download it &lt;a href="javascript:window.location.href='http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=SimpleStateMachine&amp;amp;DownloadId=42423';"&gt;here&lt;/a&gt;.&lt;br /&gt; &lt;br /&gt;As a final note:&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;Don't forget to create a database named '&lt;b&gt;ActiveRecordWorkflowSample&lt;/b&gt;'. &lt;/li&gt;&lt;li&gt;It assumes a local copy of SQLExpress, check the setup function for connection details.&lt;/li&gt;&lt;li&gt;The sample application is licensed under the Apache License, Version 2.0 so you're free to use it as you like.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>ernstnaezer</author><pubDate>Thu, 28 Aug 2008 13:13:31 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Active Record Persistence 20080828011331P</guid></item><item><title>Updated Wiki: Active Record Persistence</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active Record Persistence&amp;version=2</link><description>&lt;div class="wikidoc"&gt;
&lt;h2&gt;
Introduction
&lt;/h2&gt;The current trunk (as of aug. 28) allows users to override the default file persistence storage. This is a small howto to demonstrate the use of &lt;a href="http://www.castleproject.org/activerecord/" class="externalLink"&gt;Active Record&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; to persist workflow definitions to a database.&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
Persistence
&lt;/h2&gt;In workflow scenario's that have longer life cycle it's wise to store the workflow state somewhere that survives system failures, reboots or other unexpected things rather then keeping it in memory. This is where the persistence services of the Simple State Machine project come in.&lt;br /&gt; &lt;br /&gt;When saving a workflow we need to store enough information so that we can later recreate a statemachine and continue to run as if nothing ever happened.&lt;br /&gt; &lt;br /&gt;With that in mind we can determine that there are a couple of things that need to be stored;&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;the workflow identity,&lt;/li&gt;&lt;li&gt;it's state&lt;/li&gt;&lt;li&gt;the machine definition&lt;/li&gt;&lt;li&gt;the link with the application domain (the domain content)&lt;/li&gt;
&lt;/ul&gt; &lt;br /&gt;Storing the identity and the current state is not so difficult. Each statemachine contains a GUID that we can use and the current state has a name. &lt;br /&gt;The machine definition, as you probably know, is stored inside your boo files, so if we store the name of the file that was used to create the workflow we should have enough information to restart the machine later.&lt;br /&gt; &lt;br /&gt;The domain context is the part that reflects the state of the workflow inside your application domain. Each time we ask the Workflow Service (WS) to handle an event it can also update the state in your domain model. We'll look at this link later on.&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
The case
&lt;/h2&gt;In this howto we will be building a workflow service that can handle an account opening request at our company. Customers that apply for an account are required to send in a signed contact and make a deposit of 100 Euro to our bank account. &lt;br /&gt; &lt;br /&gt;When these two requirements are met an account manager can activate the account and the customer can start using the provided services. A final requirement is that account opening requests can be denied as long as they have not been accepted.&lt;br /&gt; &lt;br /&gt;This gives us the following workflow definition:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
workflow &amp;quot;Account Opening Request workflow&amp;quot;
 
#Event Definitions
#--------------------------------------------------------
trigger @AccountRequestSubmitted
trigger @AccountRequestDenied
trigger @AccountRequestAccepted
trigger @SignedContractReceived
trigger @DepositReceived
trigger @AccountClosed
 
#State &amp;amp; Transition Definitions
#--------------------------------------------------------
state @AccountRequestPending:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @SignedContractReceived		&amp;gt;&amp;gt; @AwaitingDeposit
 
state @AwaitingDeposit:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @DepositReceived			&amp;gt;&amp;gt; @AwaitingAccountActivation
 
state @AwaitingAccountActivation:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @AccountRequestAccepted	&amp;gt;&amp;gt; @AccountActivated
 
state @AccountActivated:
	when @AccountClosed			&amp;gt;&amp;gt; @AccountClosed
 
state @AccountClosed
state @AccountRequestDenied
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
The domain model
&lt;/h2&gt;Our domain model currently only contains one account class that represents the account opening request for the customer. As you can see we are using ActiveRecord as a persistence engine. The ModelBase class is nothing more the an abstract class that sits on top of our domain model that provides an Id.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class Account : ModelBase
{
	private string _customerName;
	private AccountState _accountState;
 
	[Property]
	public string CustomerName
	{
		get { return _customerName; }
		set { _customerName = value; }
	}
 
	[Property]
	public AccountState AccountState
	{
		get { return _accountState; }
		set { _accountState = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
Active record binding
&lt;/h2&gt;Out of the box Simple State Machine (SSM) provides support for saving workflow definitions (WFD) to disk using the .Net XmlSerializer class. When storing a WFD in a database we need a different structure. So the first thing we need to do is to create an Active Record entity that can store such a WFD. &lt;br /&gt; &lt;br /&gt;This is done by implementing the IWorkflowEntity interface and it looks like this:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class ARWorkflowEntity : IWorkflowEntity {
	private Guid _workflowId;
	private string _machineConfiguration;
	private string _currentState;
	private string _domainContextTypeDescription;
	private object _domainContextId;
	private string _domainContextStatusProperty;
 
	/// &amp;lt;summary&amp;gt;
	/// Get or set the Id of this entity
	/// &amp;lt;/summary&amp;gt;
	[PrimaryKey(Generator = PrimaryKeyType.Assigned)]
	public Guid Id {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	public Guid WorkflowId {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	[Property]
	public string MachineConfiguration {
		get { return _machineConfiguration; }
		set { _machineConfiguration = value; }
	}
 
	[Property]
	public string CurrentState {
		get { return _currentState; }
		set { _currentState = value; }
	}
 
	[Property]
	public string DomainContextTypeDescription {
		get { return _domainContextTypeDescription; }
		set { _domainContextTypeDescription = value; }
	}
 
	public object DomainContextId {
		get { return _domainContextId; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public int PersistedDomainContextID {
		get { return _domainContextId is int ? (int)_domainContextId : 0; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public string DomainContextStatusProperty {
		get { return _domainContextStatusProperty; }
		set { _domainContextStatusProperty = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt;Since Active Record doesn't know how to persist the anonymous DomainContextId property we use a little trick to unbox it via the PersistedDomainContextID property.&lt;br /&gt; &lt;br /&gt;The saving and loading of WFD is accomplished via the IWorkflowPersister interface. So the next thing is to implement a WorkflowPersister that uses Active Record.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Active record workflow persister
/// &amp;lt;/summary&amp;gt;
public class ARWorkflowPersister : IWorkflowPersister
{
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Save(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.CreateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Updates the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Update(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified workflow id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity Load(Guid workflowId)
	{
		return (IWorkflowEntity) ActiveRecordMediator.FindByPrimaryKey(typeof(ARWorkflowEntity), workflowId, true);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Completes the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Complete(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Creates the empty workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity CreateEmptyWorkflowEntity(Guid workflowId)
	{
		return new ARWorkflowEntity { WorkflowId = workflowId };
	}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
Domain binding
&lt;/h2&gt;We are almost ready to see our workflow persisting service in action. There is one last binding that we need to realize and that's the link between our application domain and the workflow. As you'll remember from the start of this article, we have a class called Account that we want to associate with a running workflow. This can be accomplished by passing an Account instance when we start a workflow.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
		
// this is where we pass the account instance to make a link between the workflow and the account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;The binding between the workflow instance and the domain entity is kept by the DomainContextRepository. Classes that implement such an interface must be able to create a string that allows us to identify the domain object that the workflow is linked to. We need this because the Workflow Service has no idea what kind object you are passing as a reference our how you would like to restore it in the case of a new event that needs to be handled. In this example we'll be using the Type name and the object's namespace.&lt;br /&gt; &lt;br /&gt;This is the code for the Active Record DomainContextRepository:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
public class ARDomainContextRepository : IDomainContextRepository {
	/// &amp;lt;summary&amp;gt;
	/// Gets the id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object GetId(object instance) {
		return ((ModelBase)instance).Id;
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Gets the type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public string GetTypeDescription(object instance) {
		var type = instance.GetType();
		return string.Format(&amp;quot;{0}, {1}&amp;quot;, type.FullName, type.Assembly.GetName().Name);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;typeDescription&amp;quot;&amp;gt;The type description.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&amp;quot;id&amp;quot;&amp;gt;The id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object Load(string typeDescription, object id) {
		var type = Type.GetType(typeDescription, true);
		return ActiveRecordMediator.FindByPrimaryKey(type, id);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified instance.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	public void Save(object instance) {
		ActiveRecordMediator.SaveAndFlush(instance);
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
The application
&lt;/h2&gt;Now that we've implemented all our bindings we can start writing a sample application that create a new account and starts the workflow. You can step through it and keep an eye on your database to see it updating the values. &lt;br /&gt; &lt;br /&gt;Here is our sample application:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
 
// then we start the workflow for the new account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
 
// we received a signed contact and would like to update the workflow state.
machineContext.HandleEvent(AccountEvent.SignedContractReceived);
 
// the next state should be that we are waiting for the deposit
Assert.That(myAccount.AccountState, Is.EqualTo(AccountState.AwaitingDeposit));
 
// this should also be stored in the database
var entity = (ARWorkflowEntity) ActiveRecordMediator.FindFirst(typeof (ARWorkflowEntity));
Assert.That(entity.CurrentState, Is.EqualTo(Convert.ToString(AccountState.AwaitingDeposit)));
 
// walk through the rest of the workflow, you can place breakpoints on these line to see the WFD updating in the DB.
machineContext.HandleEvent(AccountEvent.DepositReceived);
machineContext.HandleEvent(AccountEvent.AccountRequestAccepted);
machineContext.HandleEvent(AccountEvent.AccountClosed);
 
// and it should be completed here
Assert.That(machineContext.IsComplete);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;Attached is a zip file that contains a Visual Studio solution with all the code, libraries and the sample application as a unit test so you can see it running. Download it &lt;a href="javascript:window.location.href='http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=SimpleStateMachine&amp;amp;DownloadId=42423';"&gt;here&lt;/a&gt;.&lt;br /&gt; &lt;br /&gt;As a final note:&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;Don't forget to create a database named '&lt;b&gt;ActiveRecordWorkflowSample&lt;/b&gt;'. &lt;/li&gt;&lt;li&gt;It assumes a local copy of SQLExpress, check the setup function for connection details.&lt;/li&gt;&lt;li&gt;The sample application is licensed under the Apache License, Version 2.0 so you're free to use it as you like.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>ernstnaezer</author><pubDate>Thu, 28 Aug 2008 13:09:26 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Active Record Persistence 20080828010926P</guid></item><item><title>Updated Wiki: Active Record Persistence</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Active Record Persistence&amp;version=1</link><description>&lt;div class="wikidoc"&gt;
&lt;h2&gt;
Introduction
&lt;/h2&gt;The current trunk (as of aug. 28) allows users to override the default file persistence storage. This is a small howto to demonstrate the use of &lt;a href="http://www.castleproject.org/activerecord/" class="externalLink"&gt;Active Record&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; to persist workflow definitions to a database.&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
Persistence
&lt;/h2&gt;In workflow scenario's that have longer life cycle it's wise to store the workflow state somewhere that survives system failures, reboots or other unexpected things rather then keeping it in memory. This is where the persistence services of the Simple State Machine project come in.&lt;br /&gt; &lt;br /&gt;When saving a workflow we need to store enough information so that we can later recreate a statemachine and continue to run as if nothing ever happened.&lt;br /&gt; &lt;br /&gt;With that in mind we can determine that there are a couple of things that need to be stored;&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;the workflow identity,&lt;/li&gt;&lt;li&gt;it's state&lt;/li&gt;&lt;li&gt;the machine definition&lt;/li&gt;&lt;li&gt;the link with the application domain (the domain content)&lt;/li&gt;
&lt;/ul&gt; &lt;br /&gt;Storing the identity and the current state is not so difficult. Each statemachine contains a GUID that we can use and the current state has a name. &lt;br /&gt;The machine definition, as you probably know, is stored inside your boo files, so if we store the name of the file that was used to create the workflow we should have enough information to restart the machine later.&lt;br /&gt; &lt;br /&gt;The domain context is the part that reflects the state of the workflow inside your application domain. Each time we ask the Workflow Service (WS) to handle an event it can also update the state in your domain model. We'll look at this link later on.&lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
The case
&lt;/h2&gt;In this howto we will be building a workflow service that can handle an account opening request at our company. Customers that apply for an account are required to send in a signed contact and make a deposit of 100 Euro to our bank account. &lt;br /&gt; &lt;br /&gt;When these two requirements are met an account manager can activate the account and the customer can start using the provided services. A final requirement is that account opening requests can be denied as long as they have not been accepted.&lt;br /&gt; &lt;br /&gt;This gives us the following workflow definition:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
workflow &amp;quot;Account Opening Request workflow&amp;quot;
 
#Event Definitions
#--------------------------------------------------------
trigger @AccountRequestSubmitted
trigger @AccountRequestDenied
trigger @AccountRequestAccepted
trigger @SignedContractReceived
trigger @DepositReceived
trigger @AccountClosed
 
#State &amp;amp; Transition Definitions
#--------------------------------------------------------
state @AccountRequestPending:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @SignedContractReceived		&amp;gt;&amp;gt; @AwaitingDeposit
 
state @AwaitingDeposit:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @DepositReceived			&amp;gt;&amp;gt; @AwaitingAccountActivation
 
state @AwaitingAccountActivation:
	when @AccountRequestDenied		&amp;gt;&amp;gt; @AccountRequestDenied
	when @AccountRequestAccepted	&amp;gt;&amp;gt; @AccountActivated
 
state @AccountActivated:
	when @AccountClosed			&amp;gt;&amp;gt; @AccountClosed
 
state @AccountClosed
state @AccountRequestDenied
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
The domain model
&lt;/h2&gt;Our domain model currently only contains one account class that represents the account opening request for the customer. As you can see we are using ActiveRecord as a persistence engine. The ModelBase class is nothing more the an abstract class that sits on top of our domain model that provides an Id.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class Account : ModelBase
{
	private string _customerName;
	private AccountState _accountState;
 
	[Property]
	public string CustomerName
	{
		get { return _customerName; }
		set { _customerName = value; }
	}
 
	[Property]
	public AccountState AccountState
	{
		get { return _accountState; }
		set { _accountState = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
Active record binding
&lt;/h2&gt;Out of the box Simple State Machine (SSM) provides support for saving workflow definitions (WFD) to disk using the .Net XmlSerializer class. When storing a WFD in a database we need a different structure. So the first thing we need to do is to create an Active Record entity that can store such a WFD. &lt;br /&gt; &lt;br /&gt;This is done by implementing the IWorkflowEntity interface and it looks like this:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
[ActiveRecord]
public class ARWorkflowEntity : IWorkflowEntity {
	private Guid _workflowId;
	private string _machineConfiguration;
	private string _currentState;
	private string _domainContextTypeDescription;
	private object _domainContextId;
	private string _domainContextStatusProperty;
 
	/// &amp;lt;summary&amp;gt;
	/// Get or set the Id of this entity
	/// &amp;lt;/summary&amp;gt;
	[PrimaryKey(Generator = PrimaryKeyType.Assigned)]
	public Guid Id {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	public Guid WorkflowId {
		get { return _workflowId; }
		set { _workflowId = value; }
	}
 
	[Property]
	public string MachineConfiguration {
		get { return _machineConfiguration; }
		set { _machineConfiguration = value; }
	}
 
	[Property]
	public string CurrentState {
		get { return _currentState; }
		set { _currentState = value; }
	}
 
	[Property]
	public string DomainContextTypeDescription {
		get { return _domainContextTypeDescription; }
		set { _domainContextTypeDescription = value; }
	}
 
	public object DomainContextId {
		get { return _domainContextId; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public int PersistedDomainContextID {
		get { return _domainContextId is int ? (int)_domainContextId : 0; }
		set { _domainContextId = value; }
	}
 
	[Property]
	public string DomainContextStatusProperty {
		get { return _domainContextStatusProperty; }
		set { _domainContextStatusProperty = value; }
	}
}
&lt;/pre&gt; &lt;br /&gt;Since Active Record doesn't know how to persist the anonymous DomainContextId property we use a little trick to unbox it via the PersistedDomainContextID property.&lt;br /&gt; &lt;br /&gt;The saving and loading of WFD is accomplished via the IWorkflowPersister interface. So the next thing is to implement a WorkflowPersister that uses Active Record.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
/// &amp;lt;summary&amp;gt;
/// Active record workflow persister
/// &amp;lt;/summary&amp;gt;
public class ARWorkflowPersister : IWorkflowPersister
{
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Save(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.CreateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Updates the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Update(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified workflow id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity Load(Guid workflowId)
	{
		return (IWorkflowEntity) ActiveRecordMediator.FindByPrimaryKey(typeof(ARWorkflowEntity), workflowId, true);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Completes the specified workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowEntity&amp;quot;&amp;gt;The workflow entity.&amp;lt;/param&amp;gt;
	public void Complete(IWorkflowEntity workflowEntity)
	{
		ActiveRecordMediator.UpdateAndFlush(workflowEntity);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Creates the empty workflow entity.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;workflowId&amp;quot;&amp;gt;The workflow id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public IWorkflowEntity CreateEmptyWorkflowEntity(Guid workflowId)
	{
		return new ARWorkflowEntity { WorkflowId = workflowId };
	}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
Domain binding
&lt;/h2&gt;We are almost ready to see our workflow persisting service in action. There is one last binding that we need to realize and that's the link between our application domain and the workflow. As you'll remember from the start of this article, we have a class called Account that we want to associate with a running workflow. This can be accomplished by passing an Account instance when we start a workflow.&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
		
// this is where we pass the account instance to make a link between the workflow and the account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;The binding between the workflow instance and the domain entity is kept by the DomainContextRepository. Classes that implement such an interface must be able to create a string that allows us to identify the domain object that the workflow is linked to. We need this because the Workflow Service has no idea what kind object you are passing as a reference our how you would like to restore it in the case of a new event that needs to be handled. In this example we'll be using the Type name and the object's namespace.&lt;br /&gt; &lt;br /&gt;This is the code for the Active Record DomainContextRepository:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
public class ARDomainContextRepository : IDomainContextRepository {
	/// &amp;lt;summary&amp;gt;
	/// Gets the id.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object GetId(object instance) {
		return ((ModelBase)instance).Id;
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Gets the type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public string GetTypeDescription(object instance) {
		var type = instance.GetType();
		return string.Format(&amp;quot;{0}, {1}&amp;quot;, type.FullName, type.Assembly.GetName().Name);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Loads the specified type description.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;typeDescription&amp;quot;&amp;gt;The type description.&amp;lt;/param&amp;gt;
	/// &amp;lt;param name=&amp;quot;id&amp;quot;&amp;gt;The id.&amp;lt;/param&amp;gt;
	/// &amp;lt;returns&amp;gt;&amp;lt;/returns&amp;gt;
	public object Load(string typeDescription, object id) {
		var type = Type.GetType(typeDescription, true);
		return ActiveRecordMediator.FindByPrimaryKey(type, id);
	}
 
	/// &amp;lt;summary&amp;gt;
	/// Saves the specified instance.
	/// &amp;lt;/summary&amp;gt;
	/// &amp;lt;param name=&amp;quot;instance&amp;quot;&amp;gt;The instance.&amp;lt;/param&amp;gt;
	public void Save(object instance) {
		ActiveRecordMediator.SaveAndFlush(instance);
	}
}
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;&lt;h2&gt;
The application
&lt;/h2&gt;Now that we've implemented all our bindings we can start writing a sample application that create a new account and starts the workflow. You can step through it and keep an eye on your database to see it updating the values. &lt;br /&gt; &lt;br /&gt;Here is our sample application:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
// first we create a new account and set the initial state
var myAccount = new Account
                {
                	CustomerName = &amp;quot;Ernst&amp;quot;,
                	AccountState = AccountState.AccountRequestPending
                };
 
// then we start the workflow for the new account.
var machineContext = _workflowService.Start(&amp;quot;accountopeningworkflow&amp;quot;, myAccount, &amp;quot;AccountState&amp;quot;);
 
// we received a signed contact and would like to update the workflow state.
machineContext.HandleEvent(AccountEvent.SignedContractReceived);
 
// the next state should be that we are waiting for the deposit
Assert.That(myAccount.AccountState, Is.EqualTo(AccountState.AwaitingDeposit));
 
// this should also be stored in the database
var entity = (ARWorkflowEntity) ActiveRecordMediator.FindFirst(typeof (ARWorkflowEntity));
Assert.That(entity.CurrentState, Is.EqualTo(Convert.ToString(AccountState.AwaitingDeposit)));
 
// walk through the rest of the workflow, you can place breakpoints on these line to see the WFD updating in the DB.
machineContext.HandleEvent(AccountEvent.DepositReceived);
machineContext.HandleEvent(AccountEvent.AccountRequestAccepted);
machineContext.HandleEvent(AccountEvent.AccountClosed);
 
// and it should be completed here
Assert.That(machineContext.IsComplete);
&lt;/pre&gt; &lt;br /&gt; &lt;br /&gt;Attached is a zip file that contains a Visual Studio solution with all the code, libraries and the sample application as a unit test so you can see it running. Download it here.&lt;br /&gt; &lt;br /&gt;As a final note:&lt;br /&gt; &lt;br /&gt;&lt;ul&gt;
&lt;li&gt;Don't forget to create a database named 'ActiveRecordWorkflowSample'. &lt;/li&gt;&lt;li&gt;It assumes a local copy of SQLExpress, check the setup function for connection details.&lt;/li&gt;&lt;li&gt;The sample application is licensed under the Apache License, Version 2.0 so you're free to use it as you like.&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;</description><author>ernstnaezer</author><pubDate>Thu, 28 Aug 2008 12:57:45 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Active Record Persistence 20080828125745P</guid></item><item><title>Updated Wiki: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=15</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;Technology: .NET 3.5 (VS2008), C#3.0, Boo Language, Rhino DSL&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library written in C# that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;As for state persistence, you have to provide your own repository for persisting any domain objects you are using as the context for your state machine by implementing an IDomainContextRepository interface, but SimpleStateMachine will take care of invoking the appropriate persistence actions after each state transition, including ensuring that the persistence operation takes place within a transaction if you have your state machine marked as transactional.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
trigger @CallDialed
trigger @HungUp
trigger @CallConnected
trigger @LeftMessage
trigger @PlacedOnHold
trigger @TakenOffHold
trigger @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt; &lt;br /&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Thu, 26 Jun 2008 23:45:06 GMT</pubDate><guid isPermaLink="false">Updated Wiki: Home 20080626114506P</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=14</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;Technology: .NET 3.5 (VS2008), C#3.0, Boo Language, Rhino DSL&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library written in C# that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
trigger @CallDialed
trigger @HungUp
trigger @CallConnected
trigger @LeftMessage
trigger @PlacedOnHold
trigger @TakenOffHold
trigger @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 21:36:51 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530093651P</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=13</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;Technology: .NET 3.5 (VS2008), C#3.0, Boo Language, Rhino DSL&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library written in C# that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 16:10:33 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530041033P</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=12</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library written in C# that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:43:04 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530064304A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=11</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine (the formatting is a bit off, but you get the idea)&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:42:03 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530064203A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=10</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;The Boo Language home page: &lt;a href="http://boo.codehaus.org/" class="externalLink"&gt;http://boo.codehaus.org/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:41:18 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530064118A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=9</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and management of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. SimpleStateMachine's DSL is implemented using Boo and Rhino DSL by Ayende Rahien. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahien: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:40:23 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530064023A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=8</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and loading of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. The DSL is implemented using Boo and Rhino DSL. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahein: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimpleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:38:40 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530063840A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=7</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and loading of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a  book-in-progess on DSL's by Martin Fowler. The DSL is implemented using Boo and Rhino DSL. &lt;br /&gt; &lt;br /&gt;Martin Fowler's State Machine : &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;Building DSL's in Boo - a Manning EAP Book by Ayende Rahein: &lt;a href="http://www.manning.com/rahien/" class="externalLink"&gt;http://www.manning.com/rahien/&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:28:31 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530062831A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=6</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and loading of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a &lt;a href="http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework" class="externalLink"&gt;http://martinfowler.com/dslwip/Intro.html#TheStateMachineFramework&lt;span class="externalLinkIcon"&gt;&lt;/span&gt;&lt;/a&gt; book-in-progess on DSL's by Martin Fowler. The DSL is implemented using Boo and Rhino DSL. &lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:26:44 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530062644A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=5</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and loading of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a book-in-progess on DSL's by Martin Fowler. The DSL is implemented using Boo and Rhino DSL. &lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed  &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @CallConnected  &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage  &amp;gt;&amp;gt; @OffHook
	when @HungUp   &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold  &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold &amp;gt;&amp;gt; @Connected
	when @HungUp  &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:22:32 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530062232A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=4</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and loading of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a book-in-progess on DSL's by Martin Fowler. The DSL is implemented using Boo and Rhino DSL. &lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimleStateMachine:&lt;br /&gt; &lt;br /&gt;&lt;pre&gt;
#----------------------------------------
workflow &amp;quot;Telephone Call&amp;quot;
 
_event @CallDialed
_event @HungUp
_event @CallConnected
_event @LeftMessage
_event @PlacedOnHold
_event @TakenOffHold
_event @PhoneHurledAgainstWall
 
state @OffHook:
	when @CallDialed                         &amp;gt;&amp;gt; @Ringing	
	
state @Ringing:
	when @HungUp                            &amp;gt;&amp;gt; @OffHook
	when @CallConnected                   &amp;gt;&amp;gt; @Connected
 
state @Connected:
	when @LeftMessage                    &amp;gt;&amp;gt; @OffHook
	when @HungUp                          &amp;gt;&amp;gt; @OffHook
	when @PlacedOnHold                 &amp;gt;&amp;gt; @OnHold
	
state @OnHold:
	when @TakenOffHold                 &amp;gt;&amp;gt; @Connected
	when @HungUp                         &amp;gt;&amp;gt; @OffHook
	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed
	
state @PhoneDestroyed
&lt;/pre&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:21:40 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530062140A</guid></item><item><title>UPDATED WIKI: Home</title><link>http://www.codeplex.com/SimpleStateMachine/Wiki/View.aspx?title=Home&amp;version=3</link><description>&lt;div class="wikidoc"&gt;
&lt;b&gt;Project Description&lt;/b&gt;&lt;br /&gt;A simple state machine implementation written to replace WF in one of our projects. The interesting aspect of this library is that it comes with a DSL written in boo for quick and easy configuration and loading of state machine definitions.
&lt;br /&gt; &lt;br /&gt;SimpleStateMachine is a library that provides an easy to use state machine that can easily be configured via a custom DSL (Domain Specific Language), inspired by an example in a book-in-progess on DSL's by Martin Fowler. The DSL is implemented using Boo and Rhino DSL. &lt;br /&gt; &lt;br /&gt;The motiviation for creating this library was a dissatisfaction with the complexity and weight of Windows Workflow Foundation for creating, maintaining, testing and versioning of what should have been simple state machine workflows in our applications. It is suitable for use both in the user interface and in the middle tier and has optional facilities for directly interacting with your domain model if desired.&lt;br /&gt; &lt;br /&gt;So far there is no documentation, but the project includes a unit test suite that demonstrates most functionality and two full blown windows forms samples that demonstrate and allow expirimentation with the features of the library.&lt;br /&gt; &lt;br /&gt;SimpleStateMachine, as you would expect, allows for the definition of events, states, state transitions and user defined actions that can be executed before or after transitions. All features of the state machine itself can be configured via the DSL, and the DSL can easily be enhanced to provide extended or custom functionality.&lt;br /&gt; &lt;br /&gt;This library can be useful in production projects as well or simply serve as an example of how to create a DSL using Boo and Rhino DSL and integrate it into an application.&lt;br /&gt; &lt;br /&gt;See below for an example of the DSL syntax required to create a very simple state machine using SimleStateMachine:&lt;br /&gt; &lt;br /&gt;// multi-line&lt;br /&gt;#----------------------------------------&lt;br /&gt;workflow &amp;quot;Telephone Call&amp;quot;&lt;br /&gt; &lt;br /&gt;_event @CallDialed&lt;br /&gt;_event @HungUp&lt;br /&gt;_event @CallConnected&lt;br /&gt;_event @LeftMessage&lt;br /&gt;_event @PlacedOnHold&lt;br /&gt;_event @TakenOffHold&lt;br /&gt;_event @PhoneHurledAgainstWall&lt;br /&gt; &lt;br /&gt;state @OffHook:&lt;br /&gt;	when @CallDialed                         &amp;gt;&amp;gt; @Ringing	&lt;br /&gt;	&lt;br /&gt;state @Ringing:&lt;br /&gt;	when @HungUp                            &amp;gt;&amp;gt; @OffHook&lt;br /&gt;	when @CallConnected                   &amp;gt;&amp;gt; @Connected&lt;br /&gt; &lt;br /&gt;state @Connected:&lt;br /&gt;	when @LeftMessage                    &amp;gt;&amp;gt; @OffHook&lt;br /&gt;	when @HungUp                          &amp;gt;&amp;gt; @OffHook&lt;br /&gt;	when @PlacedOnHold                 &amp;gt;&amp;gt; @OnHold&lt;br /&gt;	&lt;br /&gt;state @OnHold:&lt;br /&gt;	when @TakenOffHold                 &amp;gt;&amp;gt; @Connected&lt;br /&gt;	when @HungUp                         &amp;gt;&amp;gt; @OffHook&lt;br /&gt;	when @PhoneHurledAgainstWall &amp;gt;&amp;gt; @PhoneDestroyed&lt;br /&gt;	&lt;br /&gt;state @PhoneDestroyed&lt;br /&gt;
&lt;/div&gt;</description><author>PlasticLIzard</author><pubDate>Fri, 30 May 2008 06:20:08 GMT</pubDate><guid isPermaLink="false">UPDATED WIKI: Home 20080530062008A</guid></item></channel></rss>