经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C# » 查看文章
C# .NET 6 使用WorkFlow Core 创建工作审批流
来源:cnblogs  作者:CoolDog;  时间:2024/6/11 9:59:28  对本文有异议

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的工步,代码如下:

  1. using WorkflowCore.Interface;
  2. using WorkflowCore.Models;
  3. namespace WorkFlowCore_Test.WorkFlows.HelloWord.Steps
  4. {
  5. public class Hello : StepBody
  6. {
  7. public override ExecutionResult Run(IStepExecutionContext context)
  8. {
  9. Console.WriteLine("Hello World!");
  10. return ExecutionResult.Next();
  11. }
  12. }
  13. }

 

  1. using WorkflowCore.Interface;
  2. using WorkflowCore.Models;
  3. namespace WorkFlowCore_Test.WorkFlows.HelloWord.Steps
  4. {
  5. public class Goodbye : StepBody
  6. {
  7. public override ExecutionResult Run(IStepExecutionContext context)
  8. {
  9. Console.WriteLine("Goodbye World!");
  10. return ExecutionResult.Next();
  11. }
  12. }
  13. }

3,添加工作流文件

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

  1. using WorkflowCore.Interface;
  2. using WorkFlowCore_Test.WorkFlows.HelloWord.Steps;
  3. namespace WorkFlowCore_Test.WorkFlows.HelloWord
  4. {
  5. public class HelloWorldWorkflow : IWorkflow
  6. {
  7. public string Id => "HelloWorld";
  8. public int Version => 1;
  9. public void Build(IWorkflowBuilder<object> builder)
  10. {
  11. builder
  12. .StartWith<Hello>()
  13. .Then<Goodbye>();
  14. }
  15. }
  16. }

4,配置和启动

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

  1. using Microsoft.AspNetCore.Mvc;
  2. using System.Xml.Linq;
  3. using WorkflowCore.Interface;
  4. using WorkflowCore.Services;
  5. using WorkflowCore.Services.DefinitionStorage;
  6. using WorkFlowCore_Test.Utils;
  7. using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
  8. using WorkFlowCore_Test.WorkFlows.AskForLeave;
  9. using WorkFlowCore_Test.WorkFlows.HelloWord;
  10. using WorkFlowCore_Test.WorkFlows.IfStatement;
  11. using WorkFlowCore_Test.WorkFlows.IfStatement.Model;
  12. using WorkFlowCore_Test.WorkFlows.Json.Steps;
  13. using WorkFlowCore_Test.WorkFlows.SimpleDecision;
  14. namespace WorkFlowCore_Test
  15. {
  16. public class Program
  17. {
  18. public static void Main(string[] args)
  19. {
  20. var builder = WebApplication.CreateBuilder(args);
  21. // Add services to the container.
  22. builder.Services.AddAuthorization();
  23. builder.Services.AddControllers();
  24. builder.Services.AddLogging(); // WorkflowCore需要用到logging service
  25. //持久化
  26. builder.Services.AddWorkflow(cfg =>
  27. {
  28. cfg.UseMySQL("server=127.0.0.1;Database=Workflow;Uid=root;Pwd=xunpai123.", true, true);
  29. });
  30. builder.Services.AddWorkflowDSL();//用来注入json和yaml
  31.  
  32. var app = builder.Build();
  33. //核心注入方法
  34. UseWorkflow(app);
  35. app.UseAuthorization();
  36. app.MapControllers();
  37. app.Run();
  38. }
  39. public static void UseWorkflow(WebApplication app)
  40. {
  41. var host = app.Services.GetService<IWorkflowHost>();
  42. #region 工步注册
  43. //c#代码注册
  44. host?.RegisterWorkflow<HelloWorldWorkflow>();
  45. //json注册
  46. #endregion
  47. host?.Start();
  48. // 通过DI获取IHostApplicationLifetime实例
  49. var applicationLifetime = app.Services.GetService(typeof(IHostApplicationLifetime)) as IHostApplicationLifetime;
  50. applicationLifetime?.ApplicationStopping.Register(() =>
  51. {
  52. host?.Stop();
  53. });
  54. }
  55. }
  56. }

 

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

  1. using Microsoft.AspNetCore.Http;
  2. using Microsoft.AspNetCore.Mvc;
  3. using Microsoft.Extensions.Configuration;
  4. using Microsoft.Extensions.DependencyInjection;
  5. using Microsoft.Extensions.Hosting;
  6. using Microsoft.Extensions.Logging;
  7. using Newtonsoft.Json;
  8. using Newtonsoft.Json.Linq;
  9. using System;
  10. using System.Diagnostics;
  11. using System.Net.Http.Json;
  12. using System.Text.Json.Nodes;
  13. using WorkflowCore.Interface;
  14. using WorkflowCore.Models;
  15. using WorkflowCore.Services;
  16. using WorkflowCore.Services.DefinitionStorage;
  17. using WorkFlowCore_Test.Utils;
  18. using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
  19. using WorkFlowCore_Test.WorkFlows.SimpleDecision;
  20. namespace WorkFlowCore_Test.Controllers
  21. {
  22. [Route("api/[controller]")]
  23. [ApiController]
  24. public class TestApiController : ControllerBase
  25. {
  26. private IWorkflowController WorkflowService;
  27. private IWorkflowHost WorkflowHost;
  28. public TestApiController(IWorkflowController workflowService, IWorkflowHost workflowHost)
  29. {
  30. WorkflowService = workflowService;
  31. WorkflowHost = workflowHost;
  32. }
  33. [Route("WorkFlowCoreTestDemo")]
  34. [HttpGet]
  35. public string WorkFlowCoreTestDemo()
  36. {
  37. //var initialData = new LeaveRequestData
  38. //{
  39. // RequestId = "11111",
  40. // RequestMsg = "开始请假"
  41. //};
  42. //WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData);
  43. WorkflowService.StartWorkflow("HelloWorld");
  44. return "true";
  45. }
  46. }
  47. }

5,效果展示

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

 

6,请假单流程

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

  1. public class LeaveRequestData
  2. {
  3. public string RequestId { get; set; }
  4. public bool ManagerApproved { get; set; }
  5. public bool HRApproved { get; set; }
  6. public string RequestMsg { get; set; }
  7. }
  1. using WorkflowCore.Interface;
  2. using WorkFlowCore_Test.WorkFlows.AskForLeave.Model;
  3. using WorkFlowCore_Test.WorkFlows.AskForLeave.Steps;
  4. using WorkFlowCore_Test.WorkFlows.SimpleDecision.Steps;
  5. namespace WorkFlowCore_Test.WorkFlows.AskForLeave
  6. {
  7. public class AskForLeaveWorkflow : IWorkflow<LeaveRequestData>
  8. {
  9. public string Id => "LeaveRequestWorkflow";
  10. public int Version => 1;
  11. public void Build(IWorkflowBuilder<LeaveRequestData> builder)
  12. {
  13. builder.StartWith(context => Console.WriteLine("提交请假申请"))
  14. .Activity("manage-audit", (data) => data.RequestMsg)
  15. .Output(data => data.ManagerApproved, step => step.Result)
  16. .Then<ManagerApprovalStep>().Input(step => step.AuditDataInfo, data => data)
  17. .If(data => data.ManagerApproved)
  18. .Do(then => then.StartWith(context => Console.WriteLine("经理审核")));
  19. }
  20. }
  21. }

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

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

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

  1. [Route("WorkFlowCoreTestDemo")]
  2. [HttpGet]
  3. public string WorkFlowCoreTestDemo()
  4. {
  5. var initialData = new LeaveRequestData
  6. {
  7. RequestId = "11111",
  8. RequestMsg = "开始请假"
  9. };
  10. WorkflowHost.StartWorkflow("LeaveRequestWorkflow", 1, initialData);
  11. //WorkflowService.StartWorkflow("HelloWorld");
  12. return "true";
  13. }

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

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

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

7,json注入

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

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

  1. {
  2. "Id": "HelloWorldJson",
  3. "Version": 1,
  4. "Steps": [
  5. {
  6. "Id": "Hello",
  7. "StepType": "",
  8. "NextStepId": "Bye"
  9. },
  10. {
  11. "Id": "Bye",
  12. "StepType": ""
  13. }
  14. ]
  15. }

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

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

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

  1. [Route("WorkFlowCoreTestDemo6")]
  2. [HttpGet]
  3. public string WorkFlowCoreTestDemo6()
  4. {
  5. WorkflowHost.StartWorkflow("HelloWorldJson", 1, null);
  6. return "";
  7. }

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

  1. {
  2. "Id": "HelloWorldJson",
  3. "Version": 1,
  4. "Steps": [
  5. {
  6. "Id": "Hello",
  7. "StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
  8. "NextStepId": "Bye"
  9. },
  10. {
  11. "Id": "Bye",
  12. "StepType": "WorkFlowCore_Test.WorkFlows.Json.Steps.HelloWorldStep, WorkFlowCore-Test, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
  13. }
  14. ]
  15. }

 

5,结语

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

原文链接:https://www.cnblogs.com/BFMC/p/18233359

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号