在 if-else 子句中跳过公共交通状态

问题描述

我正在尝试制作一个状态机,如果我的操作以 OK 状态结束,它应该发送电子邮件,或者它应该重复该操作至少 n 次,直到它以 OK 状态结束。如果超过 n 次阈值,状态机应该只是回滚并停止。

我尝试了状态和提供的一些方法,但我无法在 if 中使用 TransitionTo(State) 方法来充当“goto”并跳转到状态而忽略每一行代码低于这个点。

所以,把它放在 C# 伪代码中,它看起来像这样(这只是一种表示,以防状态机代码难以理解,我没有在我的应用程序中使用这段代码):

  numberOfRetries = 5;

CheckActionStatus:
  if (GetActionStatus() == Status.OK)
  {
    return SendEmailToUser();
  }
  else
  {
    numberOfRetries--;
  }

  if (numberOfRetries > 0)
  {
    goto CheckActionStatus;
  }
  else
  {
    return RollbackAction();
  }

以及我使用的状态机代码(请记住,numberOfRetries 的递减是在 GetActionStatus() 中完成的)

WhenEnter(Check,binder => binder
  .Then(x => x.Instance.ActionStatus = GetActionStatus())
  .If(x => x.Instance.ActionStatus == Status.OK,x => x.TransitionTo(SendEmailToUser))
  .IfElse(x => x.Instance.NumberOfRetries > 0,x => x.TransitionTo(Check),x => x.TransitionTo(Rollback)));

WhenEnter(SendEmailToUser,binder => binder
  .Then(x => Console.WriteLine("Email sent to user,everything ok!"))
  .Finalize());
WhenEnter(Rollback,binder => binder
  .Then(x => Console.WriteLine("Rollbacked!"))
  .Finalize());
            
SetCompletedWhenFinalized();

但是当我运行状态机时,我得到的输出是:

Email sent to user,everything ok!
Rollbacked!

当预期的输出应该只是

Email sent to user,everything ok!

或者只是

Rollbacked!

因为我希望如果第一个 if一个真条件,它应该转移到下一个状态(在我的例子中是 SendEmailToUser)并从那里继续执行。只有当条件评估为假时,它才应该继续第二个if(检查重试的那个)。

我错过了什么吗?

解决方法

转换到另一个状态不会转移活动执行,而是会继续下一个 IfElse 活动。所以你需要两者都是 IfElse 活动。

,

在 Chris 的回答之后,我以两种不同的方式改变了我实现状态机的方式: 方法一:嵌套if-else

WhenEnter(Check,binder => binder
  .Then(x => x.Instance.ActionStatus = GetActionStatus())
  .IfElse(x => x.Instance.ActionStatus == Status.OK,x => x.TransitionTo(SendEmailToUser),xx => xx.IfElse(xy => xy.Instance.NumberOfRetries > 0,x => x.TransitionTo(Check),x => x.TransitionTo(Rollback))));

WhenEnter(SendEmailToUser,binder => binder
  .Then(x => Console.WriteLine("Email sent to user,everything ok!"))
  .Finalize());
WhenEnter(Rollback,binder => binder
  .Then(x => Console.WriteLine("Rollbacked!"))
  .Finalize());
            
SetCompletedWhenFinalized();

这样,状态以 if-else 结束,不再执行任何其他操作,确保完成到所需状态的转换。

方法二:中间状态

WhenEnter(Check,x => x.TransitionTo(RetryCheck)));

WhenEnter(RetryCheck,binder => binder
  .IfElse(x => x.Instance.NumberOfRetries > 0,x => x.TransitionTo(Rollback)));

WhenEnter(SendEmailToUser,binder => binder
  .Then(x => Console.WriteLine("Rollbacked!"))
  .Finalize());
            
SetCompletedWhenFinalized();

这种方法也有效,我发现它更容易理解,因为您基本上只是向状态机添加另一个条件。