如何使用Stateless让触发发生时每个状态都转换为单一状态?

问题描述 投票:0回答:1

我正在使用 stateless 并具有以下状态:

  • 酒吧
  • 有故障

当故障触发发生时,我希望状态机转换到故障状态,无论之前的状态如何。有没有办法做到这一点:

machine.RegisterGlobalTrigger(Trigger.Fault, State.Faulted)

注意:我想到了以下选项,但正在寻找“更干净”的解决方案:

  1. 在每个状态下注册该触发器
  2. 创建一个“Every”父状态,每个类都是其子类,并在那里注册触发器
c# state-machine stateless-state-machine
1个回答
0
投票

它不像单行那么漂亮,但您可以使用所有可能状态的列表作为设置全局或半全局配置的方式,例如:

Enum.GetValues<State>()
        .Where(state => state != State.Faulted) // so we don't put a Faulted .Permit() on the Faulted State
        .ToList()
        .ForEach(state =>
        {
            stateMachine.Configure(state)
                .PermitIf(Trigger.Fault, State.Faulted);
        });

在此 dotnet fiddle 演示中进行测试的示例。

完整示例代码:

using System;
using System.Linq;
using Stateless;

public class Program
{
    public enum State
    {
        Foo,
        Bar,
        Faulted
    }

    public enum Trigger
    {
        Fooify,
        Barify,
        Fault
    }

    public static void Main()
    {
        // setup
        var stateMachine = new StateMachine<State, Trigger>(State.Faulted);

        stateMachine.Configure(State.Foo)
            .Permit(Trigger.Barify, State.Bar);

        stateMachine.Configure(State.Bar)
            .Permit(Trigger.Fooify, State.Foo);

        stateMachine.Configure(State.Faulted)
            .Permit(Trigger.Fooify, State.Foo)
            .Permit(Trigger.Barify, State.Bar);

        Enum.GetValues<State>()
            .Where(state => state != State.Faulted) // so we don't put a Faulted .Permit() on the Faulted State
            .ToList()
            .ForEach(state =>
            {
                stateMachine.Configure(state)
                    .PermitIf(Trigger.Fault, State.Faulted);
            });

        // using the same pattern to add transition logging to every state
        Enum.GetValues<State>()
            .ToList()
            .ForEach(state =>
            {
                stateMachine.Configure(state)
                    .OnEntry(t => Console.WriteLine($"Entering {t.Destination} from {t.Source}"));
            });

        // testing
        // To Foo, then to Faulted
        stateMachine.Fire(Trigger.Fooify);
        stateMachine.Fire(Trigger.Fault);

        // To Bar, then to Faulted
        stateMachine.Fire(Trigger.Barify);
        stateMachine.Fire(Trigger.Fault);

        Console.WriteLine("Done.");
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.