C# · 12月 31, 2021

c# – 无状态机器库 – 适当的结构方式?

人们在使用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.

考虑到这一点,你的状态机目前的结构是完美的.

最后一点要注意,请记住,同一个线程中的触发器来自于推进状态机并执行状态机逻辑可能会导致堆栈溢出异常(请参阅here关于如何解决自动提前问题).