跳到主要内容
版本:3.0.0

StateMachine

3.0.0 页面说明

StateMachine 适合把复杂状态流转从普通业务代码里拆出来。它尤其适合订单、审核、锁状态、流程状态这类“有限状态 + 明确转移规则”的场景。

推荐接入路径

第一步:启用组件

{
"Components": {
"Services": [
"Toolkit.StateMachine"
],
"Middlewares": []
}
}

第二步:定义状态枚举

public enum OrderState
{
Pending,
Processing,
Completed,
Cancelled
}

第三步:定义状态上下文

public class OrderContext : StateContext<OrderState>
{
public int OrderId { get; set; }
}

第四步:定义状态流转规则

var transitions = new Dictionary<OrderState, OrderState[]>
{
{ OrderState.Pending, new[] { OrderState.Processing, OrderState.Cancelled } },
{ OrderState.Processing, new[] { OrderState.Completed } }
};

var validator = new StateValidator<OrderState>(
transitions,
new[] { OrderState.Pending });

第五步:定义状态处理器

public class ProcessingHandler : IStateHandler<OrderState, OrderContext>
{
public OrderState State => OrderState.Processing;

public ApplyStateResult CanTransition(OrderContext context, OrderState? newState)
{
return new ApplyStateResult
{
IsSuccess = true,
Code = 200,
Message = "OK"
};
}

public void Enter(OrderContext context, OrderState? oldState)
{
}

public void Exit(OrderContext context)
{
}
}

第六步:定义业务状态机

public class OrderStateMachine : BaseStateMachine<OrderState, OrderContext>
{
public OrderStateMachine(
StateValidator<OrderState> validator,
StateHandlerManager<OrderState, OrderContext> stateHandlerManager)
: base(validator, stateHandlerManager)
{
}

protected override Task<bool> PersistStateAsync(OrderContext context)
{
return Task.FromResult(true);
}
}

第七步:执行状态变更

var context = new OrderContext
{
CurrentState = OrderState.Pending,
OrderId = 1001
};

await stateMachine.ApplyStateAsync(context, OrderState.Processing);

应该怎么理解这几层

  • StateValidator<TState>:负责“能不能转”
  • IStateHandler<TState, TContext>:负责“转之前和转之后做什么”
  • BaseStateMachine<TState, TContext>:负责“按统一流程组织起来”
  • PersistStateAsync(...):负责“最终怎么保存状态”

最容易踩坑的地方

当前处理器接口是双泛型

业务处理器应该实现:

IStateHandler<TState, TContext>

不要按旧写法写成单泛型版本。

状态机不会替你自动落库

真正的状态保存逻辑,还是要写在你自己的 PersistStateAsync(...) 里。

更推荐在 Services 层调用状态机

状态机负责规则,Service 负责业务时机。
这样职责会更清楚。

常见问题

为什么状态切换失败了

优先检查:

  • 当前状态能不能转到目标状态
  • 处理器的 CanTransition(...) 是否放行
  • PersistStateAsync(...) 是否返回成功

状态处理器里适合放什么

适合放和状态强绑定的进入、退出、副作用逻辑。
不适合把整个业务流程都塞进去。

状态机该不该替代 Service

不该。
状态机是业务规则工具,不是业务层替代品。

继续阅读