Today I finally got some time to research Stateless And you know, it’s awesome!
Key features:
- Generic support for states and triggers of any .NET type (numbers, strings, enums, etc.)
- Hierarchical states
- Entry/exit events for states
- Guard clauses to support conditional transitions
- Introspection
- Ability to store state externally (for example, in a property tracked by Linq to SQL)
- Parameterised triggers
- Reentrant states
Let's consider the following example (it's available in the Stateless source code).
Program.cs
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
-
- namespace BugTrackerExample
- {
- class Program
- {
- static void Main(string[] args)
- {
-
- bug.Assign("Joe");
- bug.Defer();
- bug.Assign("Harry");
- bug.Assign("Fred");
- bug.Close();
-
- Console.ReadKey(false);
- }
- }
- }
Bug.cs
- using System;</span>
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using Stateless;
-
- namespace BugTrackerExample
- {
- public class Bug
- {
- enum State { Open, Assigned, Deferred, Resolved, Closed }
- enum Trigger { Assign, Defer, Resolve, Close }
-
- State _state = State.Open;
- StateMachine<State, Trigger> _machine;
- StateMachine<State, Trigger>.TriggerWithParameters<string> _assignTrigger;
-
- string _title;
- string _assignee;
-
- public Bug(string title)
- {
- _title = title;
-
-
- _assignTrigger = _machine.SetTriggerParameters<string>(Trigger.Assign);
-
- _machine.Configure(State.Open)
- .Permit(Trigger.Assign, State.Assigned);
-
- _machine.Configure(State.Assigned)
- .SubstateOf(State.Open)
- .OnEntryFrom(_assignTrigger, assignee => OnAssigned(assignee))
- .PermitReentry(Trigger.Assign)
- .Permit(Trigger.Close, State.Closed)
- .Permit(Trigger.Defer, State.Deferred)
- .OnExit(() => OnDeassigned());
-
- _machine.Configure(State.Deferred)
- .OnEntry(() => _assignee = null)
- .Permit(Trigger.Assign, State.Assigned);
- }
-
- public void Close()
- {
- _machine.Fire(Trigger.Close);
- }
-
- public void Assign(string assignee)
- {
- _machine.Fire(_assignTrigger, assignee);
- }
-
- public bool CanAssign
- {
- get
- {
- return _machine.CanFire(Trigger.Assign);
- }
- }
-
- public void Defer()
- {
- _machine.Fire(Trigger.Defer);
- }
-
- void OnAssigned(string assignee)
- {
- if (_assignee != null && assignee != _assignee)
- SendEmailToAssignee("Don't forget to help the new guy.");
-
- _assignee = assignee;
- SendEmailToAssignee("You own it.");
- }
-
- void OnDeassigned()
- {
- SendEmailToAssignee("You're off the hook.");
- }
-
- void SendEmailToAssignee(string message)
- {
- Console.WriteLine("{0}, RE {1}: {2}", _assignee, _title, message);
- }
- }
- }
* Highlighted with QuickHighlighter.com