1,背景

  工作流思想在上世纪60年代就有人提出过;70年代就有人开始尝试,但是由于当时许多的限制,工作流一直没有成功的被实现;80年代才出现第一批成功的工作流系统;90年代工作流技术走向了第一个发展高峰期;90年代后至今工作流出现了很多版本,但是主旨还是不变的,为了使我们的工作变得更加高效。

  通俗点,我们经常使用的OA系统上。关于一个材料的申报,又或者个人的请假。这些流程就属于工作流(工作审批流)。其中对于审批人和各个节点是可以动态操作的。

  工作流可以通过数据库设计的形式实现,也可以使用第三方的框架Elsa,Workflow Core。本文使用第二种,并详细的介绍一下代码实现和json实现工作流程。

2,安装

  使用Nuget包管理工具安装以下的包:  

    Workflow Core 3.10.0          核心包不解释

    WorkflowCore.DSL 3.10.0        json或者yaml注入需要

    WorkflowCore.Persistence.MySQL    持久化

3,文档

  JSON / YAML Definitions - Workflow Core (workflow-core.readthedocs.io)

  WorkFlowCore 加载Json文件 - 编程代码 (cscoder.cn)

4,例子

1,创建项目

  控制台或者WebApi项目均可,这里拿WebApi项目举例。(版本用的是.net 6)

2,添加工步

  工步文件需要继承StepBody。现在添加一个Hello.cs和Goodbye的工步,代码如下:

using WorkflowCore.Interface;
using WorkflowCore.Models; namespace WorkFlowCore_Test.WorkFlows.HelloWord.Steps
{
public class Hello : StepBody
{
public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Hello World!");
return ExecutionResult.Next();
}
}
}
using WorkflowCore.Interface;
using WorkflowCore.Models; namespace WorkFlowCore_Test.WorkFlows.HelloWord.Steps
{
public class Goodbye : StepBody
{
public override ExecutionResult Run(IStepExecutionContext context)
{
Console.WriteLine("Goodbye World!");
return ExecutionResult.Next();
}
}
}

3,添加工作流文件

  工作流文件需要继承IWorkflow。现在开始添加:

using WorkflowCore.Interface;
using WorkFlowCore_Test.WorkFlows.HelloWord.Steps; namespace WorkFlowCore_Test.WorkFlows.HelloWord
{
public class HelloWorldWorkflow : IWorkflow
{
public string Id => "HelloWorld"; public int Version => 1; public void Build(IWorkflowBuilder<object> builder)
{
builder
.StartWith<Hello>()
.Then<Goodbye>();
}
}
}

4,配置和启动

  基本数据都准备好了之后,在项目启动文件进行一下配置。代码如下:

using Microsoft.AspNetCore.Mvc;
using System.Xml.Linq;
using WorkflowCore.Interface;
using WorkflowCore.Services;
using WorkflowCore.Services.DefinitionStorage;
using WorkFlowCore_Test.Utils;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.AskForLeave;
using WorkFlowCore_Test.WorkFlows.HelloWord;
using WorkFlowCore_Test.WorkFlows.IfStatement;
using WorkFlowCore_Test.WorkFlows.IfStatement.Model;
using WorkFlowCore_Test.WorkFlows.Json.Steps;
using WorkFlowCore_Test.WorkFlows.SimpleDecision; namespace WorkFlowCore_Test
{
public class Program
{
public static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddAuthorization();
builder.Services.AddControllers();
builder.Services.AddLogging(); // WorkflowCore需要用到logging service
//持久化
builder.Services.AddWorkflow(cfg =>
{
cfg.UseMySQL("server=127.0.0.1;Database=Workflow;Uid=root;Pwd=xunpai123.", true, true);
});
builder.Services.AddWorkflowDSL();//用来注入json和yaml var app = builder.Build(); //核心注入方法
UseWorkflow(app); app.UseAuthorization();
app.MapControllers();
app.Run();
} public static void UseWorkflow(WebApplication app)
{
var host = app.Services.GetService<IWorkflowHost>(); #region 工步注册
//c#代码注册
host?.RegisterWorkflow<HelloWorldWorkflow>();
//json注册
#endregion host?.Start();
// 通过DI获取IHostApplicationLifetime实例
var applicationLifetime = app.Services.GetService(typeof(IHostApplicationLifetime)) as IHostApplicationLifetime;
applicationLifetime?.ApplicationStopping.Register(() =>
{
host?.Stop();
});
} }
}

  这个时候我们添加api控制器进行调用这个helloworld的流程。代码如下:

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Diagnostics;
using System.Net.Http.Json;
using System.Text.Json.Nodes;
using WorkflowCore.Interface;
using WorkflowCore.Models;
using WorkflowCore.Services;
using WorkflowCore.Services.DefinitionStorage;
using WorkFlowCore_Test.Utils;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.SimpleDecision; namespace WorkFlowCore_Test.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class TestApiController : ControllerBase
{
private IWorkflowController WorkflowService;
private IWorkflowHost WorkflowHost;
public TestApiController(IWorkflowController workflowService, IWorkflowHost workflowHost)
{
WorkflowService = workflowService;
WorkflowHost = workflowHost;
} [Route("WorkFlowCoreTestDemo")]
[HttpGet]
public string WorkFlowCoreTestDemo()
{
//var initialData = new LeaveRequestData
//{
// RequestId = "11111",
// RequestMsg = "开始请假"
//}; //WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData); WorkflowService.StartWorkflow("HelloWorld");
return "true";
} }
}

5,效果展示

  启动后调用我们的控制器方法,然后观看console 的变化,如图:

6,请假单流程

  请假单的流程创建的话需要用到等待的函数,等待管理员进行审核后进行下一步的操作。请假单的流程代码如下:

    public class LeaveRequestData
{
public string RequestId { get; set; }
public bool ManagerApproved { get; set; }
public bool HRApproved { get; set; }
public string RequestMsg { get; set; }
}
using WorkflowCore.Interface;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
using WorkFlowCore_Test.WorkFlows.AskForLeave.Steps;
using WorkFlowCore_Test.WorkFlows.SimpleDecision.Steps; namespace WorkFlowCore_Test.WorkFlows.AskForLeave
{
public class AskForLeaveWorkflow : IWorkflow<LeaveRequestData>
{
public string Id => "LeaveRequestWorkflow";
public int Version => 1; public void Build(IWorkflowBuilder<LeaveRequestData> builder)
{
builder.StartWith(context => Console.WriteLine("提交请假申请"))
.Activity("manage-audit", (data) => data.RequestMsg)
.Output(data => data.ManagerApproved, step => step.Result)
.Then<ManagerApprovalStep>().Input(step => step.AuditDataInfo, data => data)
.If(data => data.ManagerApproved)
.Do(then => then.StartWith(context => Console.WriteLine("经理审核"))); }
}
}

  然后创建好之后,在启动文件进行注册一下:

            host?.RegisterWorkflow<AskForLeaveWorkflow, LeaveRequestData>();

  好了,接下来我们就可以用接口的形式进行模拟了。首先我们新增一个接口用来模拟申请请求代码如下:

        [Route("WorkFlowCoreTestDemo")]
[HttpGet]
public string WorkFlowCoreTestDemo()
{
var initialData = new LeaveRequestData
{
RequestId = "11111",
RequestMsg = "开始请假"
}; WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData); //WorkflowService.StartWorkflow("HelloWorld");
return "true";
}

  然后创建一个管理员的审批方法,用来审核通过或者拒绝。代码如下:

        [Route("WorkFlowCoreTestDemo4")]
[HttpGet]
public async Task<string> WorkFlowCoreTestDemo4()
{
//获取待决活动
var approval = await WorkflowHost.GetPendingActivity("manage-audit", "worker1"); if (approval != null)
{
Console.WriteLine("需要批准的" + approval.Parameters);
//提交活动成功
await WorkflowHost.SubmitActivitySuccess(approval.Token, true);//true,代表审批通过。逻辑验证在步骤里面
}
return "请假工作流";
}

  好了,这样就形成闭环了。大家可以在postman上请求测试一下,观察console的变化了。

7,json注入

  最后就是json注入的方式了,这种方式也是目前我比较倾向的方式,和前端对接就很方便的。前端按照固定的格式给后端传入json数据,后端根据json数据解析工步进行开启工作流。

  首先需要创建一个json文件,json文件代码如下:

{
"Id": "HelloWorldJson",
"Version": 1,
"Steps": [
{
"Id": "Hello",
"StepType": "",
"NextStepId": "Bye"
},
{
"Id": "Bye",
"StepType": "" }
]
}

  然后在启动文件配置,注入一下json工作流:

//json注册
var loader = app.Services.GetService<IDefinitionLoader>();
var json = System.IO.File.ReadAllText("WorkFlows/Json/JsonYaml.json");// 假设文件位于程序运行目录
// 【json注入时候,stepType写这个程序集的类名】获取并打印全限定名,包括程序集名称
//Type myClassType = typeof(HelloWorldStep);
//string fullAssemblyClassName = myClassType.AssemblyQualifiedName;
loader?.LoadDefinition(json, Deserializers.Json);

  到这里就可以了,创建一个api方法来调用看看:

        [Route("WorkFlowCoreTestDemo6")]
[HttpGet]
public string WorkFlowCoreTestDemo6()
{
WorkflowHost.StartWorkflow("HelloWorldJson", 1, null);
return "";
}

  到这里就可以实现json注入工作流了。不过细心的朋友就发现了,我给的json文件中的step的type为什么是空的呢?是因为StepType取的是项目程序集工步的类名称,因为我的电脑项目和你们的项目不一样,所以这里没有写。大家可以自行百度搜搜看,我这里还是放一下我的json例子吧。

{
"Id": "HelloWorldJson",
"Version": 1,
"Steps": [
{
"Id": "Hello",
"StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
"NextStepId": "Bye"
},
{
"Id": "Bye",
"StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" }
]
}

5,结语

  例子备注写的比较多,就不多赘述了。有问题的话就留言吧,感谢观看~

C# .NET 6 使用WorkFlow Core 创建工作审批流的更多相关文章

  1. 使用.NET Core创建Windows服务 - 使用.NET Core工作器方式

    原文:Creating Windows Services In .NET Core – Part 3 – The ".NET Core Worker" Way 作者:Dotnet ...

  2. 开源工作流引擎 Workflow Core 的研究和使用教程

    目录 开源工作流引擎 Workflow Core 的研究和使用教程 一,工作流对象和使用前说明 二,IStepBuilder 节点 三,工作流节点的逻辑和操作 容器操作 普通节点 事件 条件体和循环体 ...

  3. 使用.NET Core创建Windows服务(二) - 使用Topshelf方式

    原文:Creating Windows Services In .NET Core – Part 2 – The "Topshelf" Way 作者:Dotnet Core Tut ...

  4. Linux 之创建工作目录-mkdir

    在Linux下创建工作目录,一般使用 "mkdir" 指令,一下将介绍"mkdir"指令的使用方法,供大家参考. 一.使用帮助 在Linux终端(命令行)输入: ...

  5. Git创建工作目录与常用指令

    1.创建工作目录与常用指令 工作目录(WorkSpace)一般就是你希望Git帮助你管理的文件夹,可以是你项目的目录,也可以是一个空目录,建议不要有中文. 日常使用只要记住下图6个命令: 2.提交管理 ...

  6. .NET Core 创建Windows服务

    .NET Core 创建Windows服务 作者:高堂 原文地址:https://www.cnblogs.com/gaotang/p/10850564.html 写在前面 使用 TopShelf+Au ...

  7. 使用.NET Core创建Windows服务(一) - 使用官方推荐方式

    原文:使用.NET Core创建Windows服务(一) - 使用官方推荐方式 原文:Creating Windows Services In .NET Core – Part 1 – The &qu ...

  8. 【EFCore】利用Entityframework Core创建数据库模型

    利用Entityframework Core创建数据库模型 本文中Entityframework Core版本为v3.1.6 简介 Entity Framework (EF) Core 是微软轻量化. ...

  9. 温故知新,使用ASP.NET Core创建Web API,永远第一次

    ASP.NET Core简介 ASP.NET Core是一个跨平台的高性能开源框架,用于生成启用云且连接Internet的新式应用. 使用ASP.NET Core,您可以: 生成Web应用和服务.物联 ...

  10. Workflow Core + asp.net core 5.0 实现简单审批工作流

    我们知道企业业务系统到处都可以审批工作流的,但也很少有像OA系统一样复杂多级多条件的审批工作流需要设计,所以我们需要一个轻量级的容易上手的workflow框架,通过GitHub,我发现danielge ...

随机推荐

  1. tensorflow如何切换CPU和GPU

    import os if Bert_Use_GPU: os.environ['CUDA_VISIBLE_DEVICES'] = '0,1' #使用GPU0,1 else: os.environ['CU ...

  2. Jenkins集成GitLab的正确姿势,实现Git代码提交触发CI/CD

    ❝ jenkins和gitlab是目前DevOps工具链中最常见的,抛开gitlab-ci不谈,gitlab代码提交触发jenkins流水线是最经典的搭配. 这里就介绍下如何配置实现jenkins和g ...

  3. 【笔记】rocketMQ了解

    记录rocketMQ 忘了从哪儿保存的图了 原图链接:https://www.jianshu.com/p/2838890f3284

  4. 剑指offer21(Java)-调整数组顺序使奇数位于偶数前面(简单)

    题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数在数组的前半部分,所有偶数在数组的后半部分. 示例: 输入:nums = [1,2,3,4]输出:[1,3,2,4] 注:[ ...

  5. 力扣605(java&python)-种花问题(简单)

    题目: 假设有一个很长的花坛,一部分地块种植了花,另一部分却没有.可是,花不能种植在相邻的地块上,它们会争夺水源,两者都会死去. 给你一个整数数组  flowerbed 表示花坛,由若干 0 和 1 ...

  6. EasyNLP发布融合语言学和事实知识的中文预训练模型CKBERT

    简介: 本⽂简要介绍CKBERT的技术解读,以及如何在EasyNLP框架.HuggingFace Models和阿里云机器学习平台PAI上使⽤CKBERT模型. 导读 预训练语言模型在NLP的各个应用 ...

  7. 阿里云CDN产品经理陈章炜:边缘创新技术和落地实践

    简介: CDN除了加速外,不断被赋予更多价值.在阿里云CDN推出的<极速奔跑吧 2021>首场直播中,阿里云架构师和产品经理不仅对近期阿里云发布的CDN产品最佳实践图进行了详细解读,还对C ...

  8. WPF 通过 GifBitmapDecoder 调用 WIC 解析 Gif 和进行动画播放的简单方法

    本文告诉大家如何在 WPF 里,通过 GifBitmapDecoder 调用 WIC 层来解析 GIF 图片,然后采用动画的方式进行播放 在上一篇博客告诉大家,可以通过 GifBitmapDecode ...

  9. dotnet 读 WPF 源代码 聊聊 DispatcherTimer 的实现

    本文来告诉大家在 WPF 框架里面,是如何实现 DispatcherTimer 的功能.有小伙伴告诉我,读源代码系列的博客看不动,原因是太底层了.我尝试换一个方式切入逻辑,通过提问题和解决问题的方法, ...

  10. 有意思!一个关于 Spring 历史的在线小游戏

    发现 Spring One 的官网上有个好玩的彩蛋,分享给大家! 进到Spring One的官网,可以看到右下角有个类似马里奥游戏中的金币图标. 点击该金币之后,会打开一个新的页面,进入下面这样一个名 ...