在 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();
此方法也有效,而且我发现它更容易理解,因为您基本上只是向状态机添加另一个条件。
我正在尝试制作一个状态机,如果我的操作以 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();
此方法也有效,而且我发现它更容易理解,因为您基本上只是向状态机添加另一个条件。