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

dan*_*dcg 13 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);
    }

}
Run Code Online (Sandbox Code Playgroud)

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

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

Omn*_*mni 12

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

  • OnEntry操作仅执行如果触发已成功发射.

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

我对OnEntry/ OnExitstructuring 的经验法则是放置任何创建和逻辑,OnEntry并完成所有必需的清理OnExit.

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

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

最后一点,请记住,从推进状态机和执行状态机逻辑的同一线程中触发触发器可以并且将导致堆栈溢出异常(请参阅此处有关如何解决自动提前问题).