无状态状态机库 - 适当的结构方式?

时间:2014-10-08 22:56:09

标签: c# state-machine stateless-state-machine

在使用c#无状态库时,人们如何构建代码?

https://github.com/nblumhardt/stateless

我特别感兴趣的是它如何与注入的依赖关系以及正确的职责和分层方法联系起来。

我目前的结构涉及以下内容:

public class AccountWf
{
    private readonly AspNetUser aspNetUser;

    private enum State { Unverified, VerificationRequestSent, Verfied, Registered }
    private enum Trigger { VerificationRequest, VerificationComplete, RegistrationComplete }

    private readonly StateMachine<State, Trigger> machine;

    public AccountWf(AspNetUser aspNetUser, AccountWfService userAccountWfService)
    {
        this.aspNetUser = aspNetUser;

        if (aspNetUser.WorkflowState == null)
        {
            aspNetUser.WorkflowState = State.Unverified.ToString();
        }

        machine = new StateMachine<State, Trigger>(
        () => (State)Enum.Parse(typeof(State), aspNetUser.WorkflowState),
        s => aspNetUser.WorkflowState = s.ToString()
        );

        machine.Configure(State.Unverified)
        .Permit(Trigger.VerificationRequest, State.VerificationRequestSent);

        machine.Configure(State.VerificationRequestSent)
        .OnEntry(() => userAccountWfService.SendVerificationRequest(aspNetUser))
        .PermitReentry(Trigger.VerificationRequest)
        .Permit(Trigger.VerificationComplete, State.Verfied);

        machine.Configure(State.Verfied)
        .Permit(Trigger.RegistrationComplete, State.Registered);

    }

    public void VerificationRequest()
    {
        machine.Fire(Trigger.VerificationRequest);
    }

    public void VerificationComplete()
    {
        machine.Fire(Trigger.VerificationComplete);
    }

    public void RegistrationComplete()
    {
        machine.Fire(Trigger.RegistrationComplete);
    }

}

我们是否应该在OnEntry钩子中实现所有进程(调用服务),或者在状态转换被验证允许发生之后在外部实现进程?我很想知道如何进行交易管理。

我想我所追求的是那些已经使用无状态实现某些功能以及如何处理代码结构的人的最佳指导。

1 个答案:

答案 0 :(得分:12)

在解决结构本身之前,请注意以下几点:

  • OnEntry仅在成功触发触发器时执行

  • 在当前状态下不允许触发的触发器将抛出InvalidOperationException。如果您没有预料到异常,请考虑覆盖OnUnhandledTrigger(我发现记录未处理的触发器是查找逻辑中缺陷的好方法)。

我对OnEntry / OnExit结构的经验法则是,任何创建和逻辑都将放置OnEntry,并且所有必需的清理工作都会OnExit。< / p>

因此,在您的情况下,假设您使用注入的依赖项(并假设您没有获得这些依赖项的所有权,即其他人将管理其生命周期),您可以放置​​所有逻辑{{ 1}}。

考虑到这一点,您的状态机目前的结构方式非常好。

最后一点请注意,请记住,在推进状态机和执行状态机逻辑的同一线程内触发触发器会导致堆栈溢出异常(请参阅here如何解决自动推进问题。)