65.9K
CodeProject 正在变化。 阅读更多。
Home

Slickflow.NET Core 开源工作流引擎

starIconstarIconstarIconstarIconstarIcon

5.00/5 (11投票s)

2019年9月21日

CPOL

10分钟阅读

viewsIcon

48059

Slickflow.NET Core 开源工作流引擎

引言

对于渴望了解引擎功能的开发人员,下载版本后,他们想尝试编写代码来完成流程的开发和测试。本文试图说明如何从一个简单的流程中快速理解引擎代码编写。

背景

.NET/.NET Core 工作流引擎,带完整源代码

Github: https://github.com/besley/Slickflow

  1. 同时支持 .NET 和 .NET CORE 版本:Slickflow 是一个基于 .NET Framework 4.5 和 .NET CORE 2 的开源项目;它易于将引擎产品用于跨平台应用程序。
  2. BPMN 图形样式流程图:Slickflow 使用 BPMN 符号来描述流程图,Slickflow 设计器是 HTML5 图形编辑器,对业务流程沟通和业务分析很友好。
  3. 使用 Dapper.NET 库实现高性能:Dapper 是一个简单的 .NET 对象映射器,以速度著称,被誉为微 ORM 之王,其速度几乎与使用原始 ADO.NET 数据读取器一样快。ORM 是一个对象关系映射器,负责在数据库和编程语言之间进行映射。(参考https://dapper-tutorial.net/dapper
  4. 支持多种数据库:Slickflow 支持 SQLSERVER、ORACLE、MySQL 等数据库,它通过 Dapper.NET 扩展库实现。 .NET Core 版本使用 EF Core 支持不同的数据库产品。
  5. 支持的工作流模式:

    Wokflow Pattern

    1. 顺序:最常用的流程模式
    2. 拆分/合并:支持与/或网关,例如与/或拆分与/或合并,以及转换上的条件变量
    3. 子流程:在主流程中,子流程节点可以启动一个新的流程生命周期。
    4. 多实例:多个执行者通过多个任务实例共同处理一个任务。所有执行者都完成他们的任务,然后流程才能继续。有顺序并行模式,并且可以设置百分比计数参数以确保何时可以进入下一步。

      Muliple Instance Pattern

    5. 事件互操作:流程实例和活动实例事件委托服务,例如流程/活动的启动、执行和完成。事件还支持通过属性页面上节点的配置调用外部方法,例如 WebApi、SQL、存储过程和 Python 脚本。
    6. 定时器:与HangFire库集成,并支持CRON表达式
    7. 电子邮件:待办或逾期任务的电子邮件通知
    8. 撤回:在任务发送给下一步用户后立即撤回任务。
    9. 退回:由于一些异常,退回给上一步用户。
    10. 重发:退回后重新发送任务给原始退回用户。
    11. 反转:在完成处理后反转流程实例的活动状态。
    12. 跳跃:通过向前或向后跳过几个步骤来跳过流程。
  6. 流程版本:流程具有版本属性,可以在业务流程更改时升级新的定义。
  7. XML 缓存:运行时实例使用缓存以过期持续时间来保存 XML 流程图。

Using the Code

I:简单顺序流程编码示例

前言:对于渴望了解引擎功能的开发人员,下载版本后,他们想尝试编写代码来完成流程的开发和测试。本文试图说明如何从一个简单的流程中快速理解引擎代码编写。

版本:.NET Core 2.1

1. 创建流程图

Sequence 用于创建顺序流程,节点按顺序生成。

var pmb = ProcessModelBuilder.CreateProcess("BookSeller Process", "BookSeller Process Code", "1");
var process = pmb.Start("Start")
      .Task("Package Books", "PB001")
      .Task("Deliver Books", "DR001")
      .End("End")
      .Store();

以上代码创建了一个简单的串行流程,包含四个节点,启动节点,两个任务节点,并且Store()方法用于数据库存储流程。流程图示例如下

Sequence Flow Chart

2. 流程启动和运行

启动和运行流程是两个最常用的 API 接口。

2.1 流程启动

启动需要处理流程实例的创建,以及启动节点后任务节点的创建。示例代码如下

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "jack")
             .UseApp("BS-100", "Delivery-Books", "BS-100-LX")
             .UseProcess("BookSellerProcessCode ")
             .Start( );

流程记录列表

Sequence Activity Instance

2.2 流程运行

流程运行是从当前待办任务开始并运行到下一步的流程。解析流程时,下一步可能存在多个处理步骤,需要用户明确选择步骤列表(通常由前端用户在弹出下一步列表时指定)。这里,一个示例可以用于运行一个简单的一步实例。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "jack")
        .UseApp("BS-100", "Delivery-Books", "BS-100-LX")
        .UseProcess("BookSellerProcessCode ")
        .OnTask(8027) // TaskID
        .NextStepInt("20", "Alice")
        .Run( );

流程记录列表

Sequence Activity Instance After Running

3. 流程撤回和退回

3.1 流程撤回

如果用户在完成待办任务并发送给下一个处理人时发现错误信息,他可以自行发起撤回,并将当前流程撤回到上一步。撤回的内部处理逻辑等同于返回处理,只是发起者处于不同的位置。代码示例如下

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("20", "Alice")
           .UseApp("BS-100", "Delivery-Books", "BS-100-LX")
           .UseProcess("BookSellerProcessCode ")
           .OnTask(8027) // TaskID
           .Withdraw( );

流程记录列表

Sequence Activity Instance After Withdraw

3.2 流程退回

流程退回由当前待办任务处理人发起,并退回到流程的上一步。解析流程时,上一步可能存在多个处理步骤,需要用户明确选择步骤列表(通常由前端用户在弹出上一步列表时指定),而PrevStepInt()方法用于简化处理,仅处理返回的其中一个处理步骤。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("20", "Alice")
            .UseApp("BS-100", "Delivery-Books", "BS-100-LX")
            .UseProcess("BookSellerProcessCode ")
            .PrevStepInt()
            .OnTask(8030) // TaskID
            .SendBack( );

流程记录列表

Sequence Activity Instance After SendBack

II:简单并行分支流程编码示例

前言:对于渴望了解引擎功能的开发人员,下载版本后,他们想尝试编写代码来完成流程的开发和测试。本文试图说明如何从一个最简单的并行分支流程中快速理解引擎代码编写。

版本:.NET Core 2.1

1. 创建分支流程图

分支流程是一种常见的决策流程。本文以汽车订单流程为例,演示并行分支流程。并行分支通常用于多个部门可以同时执行任务的场景,每个独立分支也可以被视为一个串行序列片段。最后,通过汇聚节点合并多个分支。

var pmb = ProcessModelBuilder.CreateProcess(" LargeOrderProcess ", " LargeOrderProcessCode ");
var process = pmb.Start("Start")
           .Task("Large Order Received", "LOR001")
           .AndSplit("AndSplit")
           .Parallels(
               () => pmb.Branch (
                    () => pmb.Task("Engineering Review", "ER001")
                  )
                  , ( ) => pmb.Branch (
                    () => pmb.Task("Design Review", "DR001")
                  )
                )
           .AndJoin("AndJoin")
           .Task("Management Approve", "MA001")
           .End("End")
           .Store(); 

以上代码创建了一个包含两个分支的并行分支流程,分支为AndSplit-AndJoin。图中节点的属性类型通过代码直接赋值设置。流程图示例如下

parallel flowchart

2. 流程启动和运行

启动和运行流程是两个最常用的 API 接口。

2.1. 流程启动

启动需要处理流程实例的创建,以及启动节点和启动节点后任务节点的创建。示例代码如下

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "jack")
           .UseApp("PS-100", "Large-Car-Order", "PS-100-LX")
           .UseProcess("LargeOrderProcessCode")
           .Start( );

活动实例记录表如下

Parallel Activity Instance After Startup

2.2. 流程运行

流程运行是从当前待办任务开始并运行到下一步的流程。并行分支表示同时触发多个分支,如上图流程图所示:设计评审和工程评审由并行网关节点(AndSplit)同时触发,因此在活动实例表中一次性生成两个新的活动记录。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "jack")
         .UseApp("PS-100", "Large-Car-Order", "PS-100-LX")
         .UseProcess("LargeOrderProcessCode ")
         .OnTask( 8033)
         .NextStepInt("20", "Alice")
         .Run( );

活动实例记录表如下

Parallel Activity Instance After Running

3. 撤回和退回

3.1 流程撤回

如果用户在完成待办任务并发送给下一个处理人时发现错误信息,他可以自行发起撤回,并将当前流程撤回到上一步。当并行分支被撤回时,两个并行分支也同时被设置回并撤回,这表明该分支是强相关类型的两个活动。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "Jack")
         .UseApp("PS-100", "Large-Car-Order", "PS-100-LX")
         .UseProcess("LargeOrderProcessCode ")
         .OnTask(8033) // TaskID
         .Withdraw( );

活动实例记录表如下

Parallel Activity Instance After Withdraw

3.2 流程退回

流程退回由当前待办任务处理人发起,并退回到流程的上一步。如果并行分支的一个分支被退回,则默认只将当前分支之前的任务节点退回到网关,而不影响其他分支。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("20", "Alice")
          .UseApp("PS-100", "Large-Car-Order", "PS-100-LX")
          .UseProcess("LargeOrderProcessCode ")
          .PrevStepInt()
          .OnTask( 8038) // TaskID
          .SendBack( );

活动实例记录表如下

Parallel Activity Instance After SendBack

并行分支的撤销和回退在引擎中是特殊的,因为涉及到相邻分支的处理。这里只描述回退后的结果记录,回退的内部处理逻辑将另安排一篇专门文章在未来介绍。

III:简单或分支流程编码示例

前言:对于渴望了解引擎功能的开发人员,下载版本后,他们想尝试编写代码来完成流程的开发和测试。本文试图从请假流程或分支模式中快速理解引擎代码编写。

版本:.NET CORE 2.1

1. 创建或分支流程图

Or分支流程是一种常见的决策流程,用于处理不同决策场景中的业务处理,其中每个分支都可以被视为串行流程的一个片段。以下是leave流程的创建代码

var pmb = ProcessModelBuilder.CreateProcess(" LeaveRequest ", " LeaveRequestCode ");
var process = pmb.Start("Start")
         .Task("Fill Leave Days", "FLD001")
         .OrSplit("OrSplit")
         .Parallels(
                  () => pmb.Branch(
                     () => pmb.Task(
                              VertexBuilder.CreateTask("CEO Evaluate", "CEOE001"),
                              LinkBuilder.CreateTransition("days>=3")
                                 .AddCondition( ConditionTypeEnum.Expression , "Days>=3")
                              )
                      )
                 , () => pmb.Branch(
                     () => pmb.Task(
                              VertexBuilder.CreateTask("Manager Evaluate", "ME001"),
                              LinkBuilder.CreateTransition("days<3")
                                 .AddCondition(ConditionTypeEnum.Expression, "Days<=3")
                              )
                      )
                  )
          .OrJoin("OrJoin")
          .Task("the Notify HR", "HRN001")
          .End("End")
          .Store( );

以上代码创建了一个包含两个分支的OrSplit-OrJoin流程,代表实际业务流程中的请假流程。完成的流程图示例如下

Decision Flowchart

或者分支是两个条件表达式的转换。在分支网关节点的情况下,流程将根据传入条件变量天的值来决定走哪个分支。此流程可视为请假流程中请假天数的分支选择。例如,如果请假天数小于3天,则由部门经理批准。如果请假天数超过(包括)3天,则需要总经理批准。审批决策可以通过分支模式或分支模式来实现。

2. 流程启动和运行

启动和运行流程是两个最常用的 API 接口。

2.1. 流程启动

启动需要处理流程实例的创建,以及启动节点和启动节点后任务节点的创建。示例代码如下

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "jack")
          .UseApp("DS-100", "Leave-Request", "DS-100-LX")
          .UseProcess("LeaveRequestCode ")
          .Start( );

活动实例记录表如下

Decision Activity Instance After Startup

同样,以leave流程为例,第一个任务节点可以视为“提交请假单”,当员工填写完请假单后,即可视为启动流程。

2.2 流程运行

流程运行是从当前待办任务开始并运行到下一步的流程。因为是分支网关或者是分支网关,所以需要指定条件变量的名称和值来确定下一个分支路径。这里,请假天数作为条件变量需要传入。当请假天数为3天时,网关决定到CEO审批节点,因此只会选择其中一个分支进行路由。代码示例如下

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "jack")
      .UseApp("DS-100", "Leave-Request", "DS-100-LX")
      .UseProcess("LeaveRequestCode ")
      .OnTask( 8017)
      .IfCondition("Days", "3")
      .NextStepInt("20", "Alice")
      .Run( );

活动实例记录表如下

Decison Activity Instance After Running

3. 流程的撤回和退回

3.1. 流程撤回

如果用户在完成待办任务并发送给下一个处理人时发现错误信息,他可以自行发起撤回,并将当前流程撤回到上一步。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("10", "Jack")
         .UseApp("DS-100", "Leave-Request", "DS-100-LX")
         .UseProcess("LeaveRequestCode ")
         .OnTask(8017) // TaskID
         .Withdraw ( );

活动实例记录表如下

Decision Activity Instance After Withdraw

3.2 流程退回

流程退回由当前待办任务处理人发起,并退回到流程的上一步。如果并行分支的一个分支被退回,则默认只将当前分支之前的任务节点退回到网关,而不影响其他分支。

IWorkflowService wfService = new WorkflowService( );
var wfResult = wfService.CreateRunner("20", "Alice")
      .UseApp("DS-100", "Leave-Request", "DS-100-LX")
      .UseProcess("LeaveRequestCode ")
      .PrevStepInt()
      .OnTask(8020) // TaskID
      .SendBack( );

活动实例记录表如下

Decision Activity Instance After SendBack

开发工具

1) Slickflow 流程设计器

2) Slickflow WebTest 工具

GitHub 项目

摘要

  1. 以上代码可以帮助开发者快速熟悉引擎组件的接口以及简单或分支的实用功能。完整功能需要在企业版或以上版本获取。
  2. 助理开发工具中的流程设计器和Web测试工具,可以给用户直观的体验操作,也适合不同类型的业务用户;
  3. 代码创建流程和测试流程方便开发者快速学习和上手,是提高工作效率的有效途径。

历史

  • 2019年9月21日:初始版本
© . All rights reserved.