State machine implementation in C#.
- DI ready
- Async Pattern
- Safe programming with nullable types
- Works without constants and enums
- Builder for state machine creation
- Configuration of states and transitions
- Strict (default) and open transitions
- more than 95% code coverage
Product | Version |
---|---|
.NET Framework | .net 4.6.x .net 4.7.x .net 4.8.x |
.NET Standard | .net standard 2.x |
.NET Core | .net Core app 2.x .net core app 3.x |
.NET | .net 5 .net 6 .net 7 .net 8 |
You should install BlackMali.StateMachine with NuGet:
Install-Package BlackMali.StateMachine.Autofac
Or via the .NET Core command line interface:
dotnet add package BlackMali.StateMachine.Autofac
var builder = new ContainerBuilder();
builder.RegisterModule<StateMachineModule>();
builder.RegisterType<LockState>().AsSelf();
public class SlotMachine
{
private readonly IStateMachine _stateMachine;
public SlotMachine(IStateMachineBuilder builder)
{
// With DI registration -> AddState<LockState>()
builder.AddState<LockState>()
.AddStartTransition();
.AddInStateTransition()
.AddTransition<UnLockState>()
.AddTransition<EndState>();
// Without DI registration -> AddState(new UnLockState())
builder.AddState(new UnLockState())
.AddInStateTransition()
.AddTransition<LockState>()
.AddTransition<EndState>();
// Create state machine
_stateMachine = builder.Build();
}
}
// Perform state change
await _stateMachine.Transmit<LockState>();
// Or with Event
await _stateMachine.Transmit<LockState>(new StateMachineEvent());
// Or safe with exception handling
_stateMachine.OnError += (sender, args) => { };
await _stateMachine.TryTransmit<LockState>(new StateMachineEvent());
// Posts an event to the current status
await _stateMachine.Post(new StateMachineEvent());
// Safe posting
await _stateMachine.TryPost(new StateMachineEvent());
internal class LockState
: State // you can also use the interface IState without overrides
{
// optional:
public override async Task OnEnter(IStateMachineContext context)
{
await base.OnEnter(context);
Console.WriteLine("Please insert coin");
}
// optional:
public override async Task<IState?> OnTransmitted(IStateMachineContext context, StateMachineEvent @event)
{
var unLockEvent = @event as UnLockEvent;
if (unLockEvent == null)
return null;
// No state change...
if (unLockEvent.Coin == null)
return null;
// State change to UnLockState
return await context.GetState<UnLockState>();
}
// optional:
public override async Task OnExit(IStateMachineContext context)
{
// Do something...
await Task.CompletedTask;
}
}
Package | Dependencies |
---|---|
BlackMali.StateMachine | No |
BlackMali.StateMachine.Autofac | Autofac |
- XUnit
- XUnit.Runner.VisualStudio
- Autofac.Extras.Moq
- Moq
- Coverlet.Collector
Implemented with Microsoft Visual Studio Community 2022