Skip to content
Simple c# implementation of Akka's switching the behavior via Become
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Gaev.StateMachine.Tests
Gaev.StateMachine
.gitignore
Gaev.StateMachine.sln
README.md

README.md

Gaev.StateMachine

Akka.NET actor has really useful feature is switching the behavior using Become() method. It inspired me to make simple implementation to use Become() separately outside Akka.NET.

StateMachine can be used via Inheritance (IS-A) see StateMachineBase or Composition (HAS-A) see example below. StateMachine supports sync and async handlers.

See example of usage here:

public class Delivery
{
    private readonly IStateMachine it = new StateMachine();
    public string StateName;

    public Delivery()
    {
        it.Become(New);
    }

    public void Handle<TMessage>(TMessage msg) => it.Handle(msg);

    private void New()
    {
        StateName = nameof(New);
        it.Receive<Send>(msg =>
        {
            // sent logic
            it.Become(Sent);
        });
        it.Receive<Cancel>(msg =>
        {
            // cancel logic
            it.Become(Canceled);
        });
        it.ReceiveAny(NotSupported);
    }

    private void Sent()
    {
        StateName = nameof(Sent);
        it.Receive<Receive>(msg =>
        {
            // receive logic
            it.Become(Received);
        });
        it.ReceiveAny(NotSupported);
    }

    private void Canceled()
    {
        StateName = nameof(Canceled);
        it.ReceiveAny(NotSupported);
    }

    private void Received()
    {
        StateName = nameof(Received);
        it.ReceiveAny(NotSupported);
    }

    private object NotSupported(object msg)
    {
        throw new NotSupportedException();
    }

    public class Send { public string Address; }
    public class Receive { public string Feedback; }
    public class Cancel { public string Reason; }
}

class DeliveryExamples
{
    void ItCanSendThenReceive()
    {
        var delivery = new Delivery();
        delivery.Handle(new Delivery.Send { Address = "Redmond, WA 98052-7329, USA" });
        delivery.Handle(new Delivery.Receive { Feedback = "Wow, thanks!" });
    }
    void ItCanCancel()
    {
        var delivery = new Delivery();
        delivery.Handle(new Delivery.Cancel { Reason = "Running out of money" });
        delivery.Handle(new Delivery.Send { Address = "Redmond, WA 98052-7329, USA" }); // NotSupportedException
    }
    void ItCanNotCancel()
    {
        var delivery = new Delivery();
        delivery.Handle(new Delivery.Send { Address = "Redmond, WA 98052-7329, USA" });
        delivery.Handle(new Delivery.Cancel { Reason = "Running out of money" }); // NotSupportedException
    }
}
You can’t perform that action at this time.