无状态状态机库—适当的结构方式
本文关键字:结构 方式 状态 状态机 | 更新日期: 2023-09-27 18:25:57
当使用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钩子内实现所有进程(对服务的调用),还是在验证状态转换是否允许后在外部实现这些进程?如果是的话,我想知道如何进行交易管理。
我想我想要的是那些已经使用无状态实现了一些东西的人提供的一些最好的指导,以及如何处理代码结构。
在处理结构本身之前,请注意以下几点:
-
只有成功触发触发器时,才会执行
OnEntry
操作。 -
在当前状态下不允许触发的触发器将抛出
InvalidOperationException
。如果您不希望出现异常,请考虑重写OnUnhandledTrigger
(我发现记录未处理的触发器是查找逻辑中缺陷的好方法)。
我对OnEntry
/OnExit
结构的经验法则是,任何创建和逻辑都将放置在OnEntry
中,任何所需的清理都将在OnExit
中完成。
因此,在您的情况下,考虑到您使用的是注入的依赖项(并且假设您没有获得这些依赖项的所有权,即其他人将管理它们的生命周期),您可以将所有逻辑放在OnEntry
中。
考虑到这一点,您的状态机当前的结构方式非常好。
最后一点,请记住,从推进状态机和执行状态机逻辑的同一线程中触发触发器可以也将导致stackoverflow异常(请参阅此处关于如何解决自动推进问题)。