Twia.StateMachine 1.1.1

dotnet add package Twia.StateMachine --version 1.1.1
                    
NuGet\Install-Package Twia.StateMachine -Version 1.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Twia.StateMachine" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Twia.StateMachine" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="Twia.StateMachine" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Twia.StateMachine --version 1.1.1
                    
#r "nuget: Twia.StateMachine, 1.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Twia.StateMachine@1.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Twia.StateMachine&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=Twia.StateMachine&version=1.1.1
                    
Install as a Cake Tool

Twia.StateMachine

A generator of simple state machines, defined by attributes and conventions, for C# applications.

Getting started

  1. Install the Twia.StateMachine package from NuGet.
  2. Create a state machine class with triggers, states and transitions.
    • See Overview for a quick but insightful overview.
    • See Attributes for a detailed description of the attributes that can be used to define the state machine.
  3. Use the state machine.

Overview

Generates state machines based on attributes applied to a class and methods of that class.

The following UML state machine diagram:

Simple state machine

Can be defined in code as:

[StateMachine]
public partial class MyStateMachine
{
    private readonly IEngine _engine;

    public MyStateMachine(IEngine engine)
    {
        _engine = engine;
    }

    [InitialState]
    [Transition(nameof(Run), nameof(Running))]
    private partial void Stopped();

    [State]
    [OnEntry("_engine.Run()")]
    [OnExit("_engine.Stop()")]
    [Transition(nameof(Stop), nameof(Stopped))]
    [TransitionAfter("1:00:00", nameof(Stopped))]
    private partial void Running();

    [Trigger]
    public partial void Run();

    [Trigger]
    public partial void Stop();
}

The state machine will start in de Stopped state.

When the Run method is called, it will transition to the Running state, executing the _engine.Run() method on entry.

After one hour in the Running state, it will automatically transition back to the Stopped state, executing the _engine.Stop() method on entry if the engine is running.

When the Stop method is called, it will transition to the Stopped state, executing the _engine.Stop() method on entry if the engine is running.

To use the above state machine:

var engine = new StrongEngine();
var stateMachine = new MyStateMachine(engine);
stateMachine.InitializeStateMachine(); // Initialize the state machine. Brings it to the initial state.

stateMachine.Run(); // Transitions to Running state.
stateMachine.Stop(); // Transitions to Stopped state.

...

if(stateMachine.CurrentState == MyStateMachine.State.Running)
{
    stateMachine.Stop();
}

Attributes

A number of attributes are available to define the state machine.

The state machine class

The state machine class must be marked with the StateMachineAttribute attribute.

The class must be declared as partial to allow the code generator to generate the implementation.

[StateMachine]
public partial class MyStateMachine
{
}

A state machine class can be embedded in another class.

The state machine attribute has two optional parameters:

  • StateAccessible: defautls to true. Set to false to not add the IStateAccess<TState> interface to the state machine class, and thus not generate the CurrentState property.
  • Observable: defaults to false. Set to true to add the IStateMachineEvents<TState> interface to the state machine class, and thus generate the StateChanged event.

If both parameters are set to false, the state machine will not generate the State enum as a public type.

[StateMachine(Observable = false, StateAccessible = false)]
public partial class MyStateMachine
{
}

Triggers

Triggers may initiate a transition from one state to another.

A trigger is represented by a method. This method must be marked with the TriggerAttribute attribute.

To send the trigger the method must be invoked.

These methods must:

  • be declared as partial
  • have no implementation
  • have a void return type
  • have no parameters
[StateMachine]
public partial class MyStateMachine
{
    [Trigger]
    public partial void Run();
}

States

Methods that represent states must be marked with the StateAttribute attribute.

These methods must:

  • be declared as partial
  • and have no implementation
  • preferably be private, as they should not be called by users of the state machine
[StateMachine]
public partial class MyStateMachine
{
    [State]
    private partial void Running();
}

Exactly one of the states must be marked with the InitialStateAttribute attribute to indicate the starting state of the state machine. The method must follow the same rules as methods marked with the StateAttribute.

[StateMachine]
public partial class MyStateMachine
{
    [InitialState]
    private partial void Stopped();
}

Transitions

A transition is triggered by a given trigger and will bring the state machine to the target state.

A transition may have a guard condition that must evaluate to true for the transition to activate.

A transition may have an action that is executed when the transition executes.

Transitions are defined on the state the transition originates from, the source state. The target state of a transition may be another state, or it may transition back to the source state.

[StateMachine]
public partial class MyStateMachine
{
    [State]
    [Transition(nameof(Stop), nameof(Stopped))]
    private partial void Running();
}

The example shows that, when in state Running, on reception of the trigger Stop the state should transition to the state Stopped.

⚠️ The Transition attribute can only be used on methods that also have the State or InitialState attribute.

Guard conditions
[StateMachine]
public partial class MyStateMachine
{
    [State]
    [Transition(nameof(Stop), nameof(Stopped), Condition = "_engine.Speed > 1000")]
    private partial void Running();
}

The example shows that, when in state Running, on reception of the trigger Stop, and when the condition _engine.Speed > 1000 is true, then the state should transition to the state Stopped.

Action on transition
[StateMachine]
public partial class MyStateMachine
{
    [State]
    [Transition(nameof(Stop), nameof(Stopped), Action = "_engine.Stop()")]
    private partial void Running();
}

The example shows that, when in state Running, on reception of the trigger Stop, the action _engine.Stop() will be executed, and the state will transition to the state Stopped.

Entry and Exit actions

Actions can be define that should be executed on entry of a state, or on exit of a state.

[StateMachine]
public partial class MyStateMachine
{
    [InitialState]
    [Transition(nameof(Run), nameof(Running))]
    private partial void Stopped();

    [State]
    [OnEntry("_engine.Run()")]
    [OnExit("_engine.Stop()")]
    [Transition(nameof(Stop), nameof(Stopped))]
    [TransitionAfter("1:00:00", nameof(Stopped))]
    private partial void Running();
 }

Generated methods, types, and properties

In addition to the states and trigger, the following methods, types and properties are generated for each state machine class:

  • Method void InitializeStateMachine(). Initializes the state machine and brings it to the initial state.
  • Enum State, embedded in the state machine class. Contains all states of the state machine as enum members. Enum State is only generated if at least on of the StateAccessible and Observable parameters of the StateMachineAttribute is true.
  • Raad-only property State CurrentState { get; }. Returns the current state of the state machine. Property CurrentState is only generated if the StateAccessible parameter of the StateMachineAttribute is true.
  • Event event EventHandler<StateChangedEventArgs<TState>>? OnStateChanged;. Event to be notified about state changes. Event OnStateChanged is only generated if the Observable parameter of the StateMachineAttribute is true.
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETStandard 2.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 105 4/6/2026
1.0.1 125 3/9/2026

1.1.1:

 - FIX: Generate full namespace for the EventHandler and StateChangedEventArgs usage in the state machine.

1.1.0:

 - ADD: Ability in the `StateMachineAttribute` to hide current state from the outside world.
 - ADD: Support to report state changes as an event.

 - FIX: Version of generator in GeneratedCodeAttribute.

1.0.1:

 -FIX: Library is now available in the project that includes the NuGet package.

1.0.0:

 Initial Version.

 - ADD: Initial implementation of the code generator for state machines.