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

Skip a Mass Transit state in an if-else clause

我正在尝试制作一个状态机,如果我的操作以 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)并从那里继续执行。只有当条件评估为 false 时,它​​才应该继续到第二个 if(检查重试的那个)。

我是不是漏掉了什么?

转换到另一个状态不会转移 activity 执行,它会继续下一个 IfElse activity。所以你需要两者都是 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, 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();

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