0

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

我玩弄了状态和提供的一些方法,但是我无法设法在 if 中使用 TransitionTo(State) 方法来充当“goto”并跳转到 State 忽略这一点以下的每一行代码.

所以,把它放在 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(检查重试的那个)。

我错过了什么吗?

4

2 回答 2

1

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

于 2021-07-08T15:58:48.650 回答
0

在克里斯的回答之后,我以两种不同的方式改变了我实现状态机的方式:方法1:嵌套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, binder => binder
  .Then(x => x.Instance.ActionStatus = GetActionStatus())
  .IfElse(x => x.Instance.ActionStatus == Status.OK,
    x => x.TransitionTo(SendEmailToUser),
    x => x.TransitionTo(RetryCheck)));

WhenEnter(RetryCheck, binder => binder
  .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();

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

于 2021-07-09T08:36:10.700 回答