You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Windows Workflow 4状态机创建内存持久化存储并恢复实例?

如何在Windows Workflow 4中基于自定义状态类恢复状态机实例

我完全理解你的需求:想要绕开WF4默认的严格序列化机制,用自己的轻量状态类(比如你的StateObject)直接恢复状态机到指定状态,同时保留接口注入服务的能力,还要避免那种在开头加状态跳转的别扭做法。下面是几个可行的实践方向,结合代码示例帮你实现目标:

核心思路:自定义轻量持久化 + 状态机"定向唤醒"

WF4状态机的核心是通过Bookmark实现挂起和恢复,但默认持久化会序列化整个实例。我们可以换个思路:只保存你关心的关键状态(就是StateObject里的内容),恢复时直接创建新的状态机实例,通过Bookmark直接推进到目标状态,而非反序列化旧实例。


1. 改造状态机:给每个状态添加可唤醒入口

首先,让状态机的每个业务状态都拥有一个专属的Bookmark,同时支持接收StateObject作为输入参数,用来恢复内部变量。示例代码如下:

public class MyStateMachine : StateMachine
{
    // 注入的服务接口
    public InArgument<IMyService> MyService { get; set; }
    // 自定义状态跟踪对象
    public InArgument<StateObject> StateTracker { get; set; }

    public MyStateMachine()
    {
        // 定义业务状态
        var pendingState = new State { DisplayName = "Pending" };
        var approvedState = new State { DisplayName = "Approved" };
        var rejectedState = new State { DisplayName = "Rejected" };

        // Pending状态:创建Bookmark作为恢复入口,同时使用StateTracker恢复变量
        pendingState.Entry = new Sequence
        {
            Activities =
            {
                new CreateBookmark { Name = "Resume_Pending" },
                new WriteLine { 
                    Text = new InArgument<string>(ctx => 
                        $"恢复到Pending状态,当前值:{StateTracker.Get(ctx).Value}") 
                },
                // 这里添加Pending状态的业务逻辑,可注入MyService使用
            }
        };

        // Approved状态同理
        approvedState.Entry = new Sequence
        {
            Activities =
            {
                new CreateBookmark { Name = "Resume_Approved" },
                new WriteLine { 
                    Text = new InArgument<string>(ctx => 
                        $"恢复到Approved状态,更新日期:{StateTracker.Get(ctx).LastUpdated:yyyy-MM-dd}") 
                }
            }
        };

        // 配置状态转换(根据你的业务需求定义)
        this.InitialState = pendingState;
        this.States.Add(pendingState);
        this.States.Add(approvedState);
        this.States.Add(rejectedState);
    }
}

2. 实现自定义持久化存储

创建你的InMemoryPersistentStore,只存储StateObject和目标状态名称,完全不需要序列化整个工作流:

public class InMemoryPersistentStore
{
    private StateObject _savedState;
    private string _targetStateName;

    public InMemoryPersistentStore(StateObject initialState)
    {
        _savedState = initialState;
        _targetStateName = initialState.State;
    }

    // 挂起时调用:保存当前状态和状态名称
    public void SaveCurrentState(StateObject currentState, string stateName)
    {
        _savedState = currentState;
        _targetStateName = stateName;
    }

    // 获取保存的状态信息
    public (StateObject State, string TargetStateName) GetSavedState() 
        => (_savedState, _targetStateName);
}

3. 实现恢复逻辑:创建实例 + 定向唤醒目标状态

通过WorkflowFactory来封装恢复流程,同时处理服务注入:

public class WorkflowFactory
{
    private readonly IServiceProvider _serviceProvider;

    // 注入服务容器,用来提供状态机需要的服务实例
    public WorkflowFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    public WorkflowInstance ResumeFrom(InMemoryPersistentStore store)
    {
        var (savedState, targetState) = store.GetSavedState();
        
        // 1. 创建新的状态机实例
        var stateMachine = new MyStateMachine();
        
        // 2. 注入所需服务和状态跟踪对象
        var inputs = new Dictionary<string, object>
        {
            { nameof(MyStateMachine.MyService), _serviceProvider.GetService<IMyService>() },
            { nameof(MyStateMachine.StateTracker), savedState }
        };

        // 3. 创建WorkflowApplication并定向唤醒目标状态的Bookmark
        var workflowApp = new WorkflowApplication(stateMachine, inputs);
        workflowApp.ResumeBookmark($"Resume_{targetState}", null);
        
        return new WorkflowInstance(workflowApp);
    }
}

// 简单封装WorkflowApplication,对外暴露业务方法
public class WorkflowInstance
{
    private readonly WorkflowApplication _app;

    public WorkflowInstance(WorkflowApplication app)
    {
        _app = app;
    }

    public void DoSomething()
    {
        // 继续执行状态机的业务逻辑
        _app.Run();
    }
}

4. 使用示例

完全符合你期望的调用方式:

// 初始化存储(模拟从持久化介质加载的状态)
var store = new InMemoryPersistentStore(new StateObject() { State = "Pending", Value = 10 });

// 通过工厂恢复实例
var serviceProvider = new ServiceCollection()
    .AddScoped<IMyService, MyService>()
    .BuildServiceProvider();
var factory = new WorkflowFactory(serviceProvider);
var workflowInstance = factory.ResumeFrom(store);

// 执行恢复后的业务逻辑
workflowInstance.DoSomething();

关键优势说明

  • 避免默认序列化的繁琐:只保存你关心的简单类型状态,不需要处理整个工作流实例的序列化问题,也不存在版本兼容风险。
  • 符合状态机设计理念:通过Bookmark直接唤醒目标状态的入口逻辑,不是先进入初始状态再跳转,完全契合状态机的状态驱动设计。
  • 灵活的依赖注入:每次恢复都创建新的状态机实例,通过IServiceProvider注入所需服务,完美支持接口注入模式。

关于StateMachineStateTracker的替代

你提到的StateMachineStateTracker确实依赖Sql持久化且文档匮乏,它的核心思路其实和上面的方案类似,但被绑定到了Sql存储上。我们自己实现的方案更灵活,可适配任何存储介质(内存、文件、自定义数据库等),也不需要处理复杂的序列化约束。

内容的提问来源于stack exchange,提问作者The Senator

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:51:38