.NET Stateless同触发多守卫条件不满足时状态机报错问题求解
解决方案
针对你遇到的Stateless状态机触发报错问题,有两种简洁的解决方式,无需新增状态或触发,直接在现有配置上补充逻辑即可:
方案一:使用IgnoreIf忽略无效触发
当数据不存在时,直接忽略Initialized触发,让状态机保持在WaitingForData状态,不会抛出错误。修改后的状态配置如下:
var sm = new StateMachine<MyStates, MyTriggers>(MyStates.WaitingForData); sm.Configure(MyStates.WaitingForData) .PermitIf(MyTriggers.Initialized, MyStates.RequestingNewData, () => IsDataPresent() && !IsDataUpToDate()) .PermitIf(MyTriggers.Initialized, MyStates.Complete, () => IsDataPresent() && IsDataUpToDate()) // 新增:数据不存在时忽略触发,状态保持不变 .IgnoreIf(MyTriggers.Initialized, () => !IsDataPresent()); sm.Configure(MyStates.RequestingNewData) .OnEntryAsync(() => { dataService.RequestNewDataAsync().Completed(task => { sm.FireAsync(MyTriggers.NewDataArrived); }); return Task.CompletedTask; }) .Permit(MyTriggers.NewDataArrived, MyStates.Complete); await sm.FireAsync(MyTriggers.Initialized);
方案二:使用PermitReentryIf重入当前状态
如果需要在数据不存在时触发WaitingForData的OnEntry逻辑(当前示例中没有,但后续可能添加),可以用重入当前状态的方式替代忽略:
sm.Configure(MyStates.WaitingForData) .PermitIf(MyTriggers.Initialized, MyStates.RequestingNewData, () => IsDataPresent() && !IsDataUpToDate()) .PermitIf(MyTriggers.Initialized, MyStates.Complete, () => IsDataPresent() && IsDataUpToDate()) // 新增:数据不存在时重入WaitingForData状态 .PermitReentryIf(MyTriggers.Initialized, () => !IsDataPresent());
原理说明
Stateless要求同一状态下的同一触发,所有守卫条件必须覆盖所有可能的场景——要么允许过渡到某个状态,要么明确忽略/重入原状态。补充上述逻辑后,Initialized触发的所有分支都被覆盖,不会再因无匹配守卫而抛出InvalidOperationException。
内容的提问来源于stack exchange,提问作者AceGambit
相关产品推荐
相关产品推荐

