Skip to content

Repository files navigation

NState

A state machine for .NET, licensed under LGPL.

I would love to know if you use NState in your application. I can be contacted on ben@bj.ma.

Example:

//arrangevartransitions=newIStateTransition<BugState,TransitionActionStatus>[]{newBugTransition.Open(),newBugTransition.Assign(newBugTransitionAction.Assign()),newBugTransition.Defer(newBugTransitionAction.Defer()),newBugTransition.Resolve(newBugTransitionAction.Resolve()),newBugTransition.Close(newBugTransitionAction.Close()),};varmyStateMachine=newStateMachine<BugState,TransitionActionStatus>("example",transitions,initialState:newBugState.Open());//actvarbug=newBug("my bug name",myStateMachine);//Bug type inherits from Stateful base type//assertAssert.That(bug.CurrentState,Is.TypeOf<BugState.Open>());//true	//actbug.Assign("example@example.com",outtransitionActionStatus);//triggers a transition of the state machine//assertAssert.That(bug.CurrentState,Is.TypeOf<BugState.Assigned>());//trueAssert.That(transitionActionStatus,Is.EqualTo(TransitionActionStatus.Success));//trueAssert.That(bug.AssigneeEmail,Is.EqualTo("example@example.com"));//true//actvarjson=myStateMachine.ToJson();varmyDeserializedStateMachine=newStateMachine<BugState,TransitionActionStatus>("example",_transitions,initialState:newBugState.Open());myDeserializedStateMachine.InitializeFromJson(json);//assertAssert.That(myDeserializedStateMachine.CurrentState,Is.TypeOf<BugState.Assigned>());//true

Features

  • easy construction of trees of interdependent or orthogonal state machines
  • supports making domain objects stateful
  • trivial state machine tree persistence and retrieval to/from JSON
  • transition conditions, exit and entry actions
  • transition actions are fully-fledged types enabling use of dependency injection to maintain clean, testable code even for complex behavior
  • initial and final state specification

How to use

0. Get it

	nuget install nstate

1. Create some states

publicabstractclassBugState:State{publicclassAssigned:BugState{}publicclassClosed:BugState{}publicclassDeferred:BugState{}publicclassOpen:BugState{}publicclassResolved:BugState{}}

2. Define your stateful type

publicclassBug:Stateful<BugState,TransitionActionStatus>{publicBug(stringtitle,IStateMachine<BugState,TransitionActionStatus>stateMachine):base(stateMachine){Title=title;}publicstringTitle{get;set;}publicstringAssigneeEmail{get;set;}publicstringClosedByName{get;set;}publicBugOpen(outTransitionActionStatustransitionActionStatus){returnTriggerTransition(this,newBugState.Open(),outtransitionActionStatus);}publicBugAssign(stringassigneeEmail,outTransitionActionStatustransitionActionStatus){dynamicdto=newExpandoObject();dto.AssigneeEmail=assigneeEmail;returnTriggerTransition(this,newBugState.Assigned(),outtransitionActionStatus,dto);}publicvoidDefer(outTransitionActionStatustransitionActionStatus){returnTriggerTransition(this,newBugState.Deferred(),outtransitionActionStatus);}publicvoidResolve(outTransitionActionStatustransitionActionStatus){returnTriggerTransition(this,newBugState.Resolved(),outtransitionActionStatus);}publicBugClose(stringclosedByName,outTransitionActionStatustransitionActionStatus){dynamicdto=newExpandoObject();dto.ClosedByName=closedByName;returnTriggerTransition(this,newBugState.Closed(),outtransitionActionStatus,dto);}}

3. Define your transitions

publicpartialclassBugTransition{publicclassResolve:StateTransition<BugState,TransitionActionStatus>{publicResolve(BugTransitionAction.ResolvetransitionAction):base(transitionAction:transitionAction){}publicoverrideBugState[]StartStates{get{returnnew[]{newBugState.Assigned(),};}}publicoverrideBugState[]EndStates{get{returnnew[]{newBugState.Resolved(),};}}}publicclassAssign:StateTransition<BugState,TransitionActionStatus>{//...}//etc.}

4. Define any transition actions

publicpartialclassBugTransitionAction{publicclassAssign:TransitionAction<BugState,TransitionActionStatus>{publicoverrideTransitionActionStatusRun(BugStatetargetState,IStateMachine<BugState,TransitionActionStatus>stateMachine,dynamicstatefulObject,dynamicdto=null){if(dto==null){thrownewArgumentNullException("dto");}if(dto.AssigneeEmail==null){thrownewException("AssigneeEmail not supplied.");}statefulObject.AssigneeEmail=dto.AssigneeEmail;returnTransitionActionStatus.Success;}}//etc.}

5. Instantiate your state machine

//...vartransitions=newIStateTransition<BugState,TransitionActionStatus>[]{newBugTransition.Open(),newBugTransition.Assign(newBugTransitionAction.Assign()),newBugTransition.Defer(newBugTransitionAction.Defer()),newBugTransition.Resolve(newBugTransitionAction.Resolve()),newBugTransition.Close(newBugTransitionAction.Close()),};_stateMachine=newStateMachine<BugState,TransitionActionStatus>("example",transitions,initialState:newBugState.Open());//...

6. Work with your stateful object

//arrangevarbug=newBug("my bug name",_stateMachine);//actbug.Assign("example@example.com",outtransitionActionStatus);//assertAssert.That(bug.CurrentState,Is.TypeOf(BugState.Assigned));//trueAssert.That(transitionActionStatus,Is.EqualTo(TransitionActionStatus.Success));//trueAssert.That(bug.AssigneeEmail,Is.EqualTo("example@example.com"));//true

7. Persist and restore your state machine

//...varjson=_myStateMachine.ToJson();//send json to Couch or somewhere...//later...varmyStateMachine=newStateMachine<BugState,TransitionActionStatus>("example",_transitions,initialState:newBugState.Open());myStateMachine.InitializeFromJson(json);//continue where you left off...

How to build and/or run the tests

  1. Run /build/build.bat
  2. Type in the desired option
  3. Hit return

License & Copyright

This software is released under the GNU Lesser GPL. It is Copyright 2013, Ben Aston. I may be contacted at ben@bj.ma.

How to Contribute

Pull requests including bug fixes, new features and improved test coverage are welcomed. Please do your best, where possible, to follow the style of code found in the existing codebase.

Bitdeli Badge

About

A state machine for .NET.

Resources

Stars

45 stars

Watchers

5 watching

Forks

Releases

Packages

Used by

Contributors

Languages