workflow-core 简介
Posted keep-study-to-die
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了workflow-core 简介相关的知识,希望对你有一定的参考价值。
最近想做一个OA相关的网站开发,一直都听说有workflow的东西,之前也断断续续学习过 Workflow Foundation 4.0,还是没有搞明白到底能够用它做什么
但还是觉得workflow在某种情形下应该可以适用,虽然还没有答案,网上搜楼了一通,发现一个workflow-core的东西,觉得挺有意思,遂停下来,琢磨一下,现分享与大家。
* 简介
如主页上介绍的,workflow core作为一个轻量级workflow引擎,可以嵌入到项目中,其底层是用.net standard 2.0开发,可以用来追踪长时间运行的任务状态,功能也比较强大,支持插件形式持久化,和多节点并行处理,貌似很牛。并且目前有给一个 Conductor 项目,就是使用workflow core作为内核的workflow服务器(原来运行workflow,需要单独的一个服务器啊),Conductor这里就不展开了。workflow core支持fluent语法,写起来也非常美观,虽然没有WF那样有图形化的操作界面,但感觉代码比较干净。
- 插播.Net Standard 2.0 简介
开始的时候不了解什么是.Net Standard 2.0,这篇文章讲得比较清楚,.Net Standard 与 .Net Framework关系 还有这个.NET Core 2.0 是您的最好选择吗,原来微软为了统一.Net 的各种平台,出了一个.Net Standard 标准库,基于这个库开发的,可以应用于.net framework 4.6.1以上版本,也可以应用于.net core 2.0以上
了解了相关内容后,直接打开说明,照着例子走一遭了。
* 示例1
新建一个项目,指明使用.net framework 4.6.1以上,新建项目后,在Package Manager Console中,安装workflow core:Install-Package WorkflowCore
,安装这个包会默认安装一系列的依赖包
可能由于版本的关系,还需要另外安装两个包:Microsoft.Extensions.Logging 和 Microsoft.Extensions.Logging.Debug。这样就可以按照Sample 01开始编写代码了
Sample01是一个helloworld,包含了几部分内容:
1. 构建StepBody,就是workflow中需要执行的内容,每个类继承自StepBody这个虚拟类,重载ExecutionResult Run(IStepExecutionContext context),这个函数中完成所需的工作
1 public class HelloWorld : StepBody 2 { 3 private ILogger logger; 4 5 public HelloWorld(ILoggerFactory loggerFactory) 6 { 7 logger = loggerFactory.CreateLogger<HelloWorld>(); 8 } 9 10 public override ExecutionResult Run(IStepExecutionContext context) 11 { 12 Console.WriteLine("Hello world, workflow"); 13 logger.LogInformation("Helloworld workflow"); 14 15 return ExecutionResult.Next(); 16 } 17 } 18 19 20 public class GoodbyeWorld : StepBody 21 { 22 private ILogger logger; 23 24 public GoodbyeWorld(ILoggerFactory loggerFactory) 25 { 26 logger = loggerFactory.CreateLogger<GoodbyeWorld>(); 27 } 28 29 public override ExecutionResult Run(IStepExecutionContext context) 30 { 31 Console.WriteLine("Workflow, Goodbye"); 32 logger.LogInformation("Goodbye workflow"); 33 34 return ExecutionResult.Next(); 35 } 36 } 37 38 public class SleepStep : StepBody 39 { 40 private ILogger logger; 41 42 public SleepStep(ILoggerFactory loggerFactory) 43 { 44 logger = loggerFactory.CreateLogger("SleepStep"); 45 } 46 47 public override ExecutionResult Run(IStepExecutionContext context) 48 { 49 Thread.Sleep(1000); 50 51 logger.LogInformation("Sleeped"); 52 53 return ExecutionResult.Next(); 54 } 55 }
2. 构建workflow,实现IWorkflow接口,每个workflow有一个Id和一个Version,标明这个workflow的身份,这里通过两种方法构建了HelloWorkflow,
1 public class HelloWorkflow : IWorkflow 2 { 3 public string Id => "HelloWorkflow"; 4 5 public int Version => 1; 6 7 public void Build(IWorkflowBuilder<object> builder) 8 { 9 builder.StartWith(context => 10 { 11 Console.WriteLine("Hello world"); 12 return ExecutionResult.Next(); 13 }) 14 .Then(context => 15 { 16 Thread.Sleep(500); 17 Console.WriteLine("sleeped"); 18 return ExecutionResult.Next(); 19 }) 20 .Then(context => 21 { 22 Console.WriteLine("Goodbye world"); 23 return ExecutionResult.Next(); 24 }); 25 } 26 } 27 28 public class HelloWorkflow2 : IWorkflow 29 { 30 public string Id => "HelloWorkflow"; 31 32 public int Version => 2; 33 34 public void Build(IWorkflowBuilder<object> builder) 35 { 36 builder.StartWith<HelloWorld>() 37 .Then<SleepStep>() 38 .Then<GoodbyeWorld>(); 39 } 40 }
3. 万事俱备,准备让workflow运行起来。第一步当然是需要搭建service,Workflow Core通过Injection命名空间的ServiceCollection添加了Workflow相关的服务,对于有参数的StepBody,需要先通过service的AddTransient函数注册,这样才能正确的构造对象
1 /// <summary> 2 /// 配置workflow 3 /// </summary> 4 /// <returns></returns> 5 private IServiceProvider ConfigureServices() 6 { 7 //setup dependency injection 8 IServiceCollection services = new ServiceCollection(); 9 services.AddLogging(); 10 services.AddWorkflow(); 11 //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); 12 13 // 这些个构造函数带参数的,需要添加到transient中 14 services.AddTransient<HelloWorld>(); 15 services.AddTransient<GoodbyeWorld>(); 16 services.AddTransient<SleepStep>(); 17 18 var serviceProvider = services.BuildServiceProvider(); 19 20 //config logging 21 var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); 22 loggerFactory.AddProvider(new DebugLoggerProvider()); 23 24 return serviceProvider; 25 }
接下来,启动workflow 主机,并启动一次workflow,将整个窗体代码贴一下,这样比较清晰
1 using Microsoft.Extensions.DependencyInjection; 2 using Microsoft.Extensions.Logging; 3 using Microsoft.Extensions.Logging.Console; 4 using Microsoft.Extensions.Logging.Debug; 5 using System; 6 using System.Collections.Generic; 7 using System.Linq; 8 using System.Text; 9 using System.Threading.Tasks; 10 using System.Windows; 11 using System.Windows.Controls; 12 using System.Windows.Data; 13 using System.Windows.Documents; 14 using System.Windows.Input; 15 using System.Windows.Media; 16 using System.Windows.Media.Imaging; 17 using System.Windows.Navigation; 18 using System.Windows.Shapes; 19 using WorkflowCore.Interface; 20 using WorkflowCore.Services; 21 using WorkFlowCoreTest.MyWorkflow; 22 23 namespace WorkFlowCoreTest 24 { 25 /// <summary> 26 /// Interaction logic for MainWindow.xaml 27 /// </summary> 28 public partial class MainWindow : Window 29 { 30 IServiceProvider serviceProvider = null; 31 bool serviceStarted = false; 32 33 public MainWindow() 34 { 35 InitializeComponent(); 36 } 37 38 private void StartWorkflow() 39 { 40 41 if (serviceProvider == null) 42 { 43 serviceProvider = ConfigureServices(); 44 var host1 = serviceProvider.GetService<IWorkflowHost>(); 45 46 host1.RegisterWorkflow<HelloWorkflow>(); 47 host1.RegisterWorkflow<HelloWorkflow2>(); 48 } 49 50 51 var host = serviceProvider.GetService<IWorkflowHost>(); 52 var wd = host.Registry.GetDefinition("HelloWorkflow"); 53 54 // 如果host启动了,不能再次启动,但没有判断方法 55 if (!serviceStarted) 56 { 57 host.Start(); 58 serviceStarted = true; 59 } 60 61 62 // 启动workflow工作流 63 host.StartWorkflow("HelloWorkflow", 1, data: null); // 64 //host.StartWorkflow("HelloWorkflow");//, 2, data: null, 默认会启用版本高的 65 } 66 67 private void StopWorkflow() 68 { 69 var host = serviceProvider.GetService<IWorkflowHost>(); 70 71 host.Stop(); 72 serviceStarted = false; 73 } 74 75 /// <summary> 76 /// 配置workflow 77 /// </summary> 78 /// <returns></returns> 79 private IServiceProvider ConfigureServices() 80 { 81 //setup dependency injection 82 IServiceCollection services = new ServiceCollection(); 83 services.AddLogging(); 84 services.AddWorkflow(); 85 //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow")); 86 87 // 这些个构造函数带参数的,需要添加到transient中 88 services.AddTransient<HelloWorld>(); 89 services.AddTransient<GoodbyeWorld>(); 90 services.AddTransient<SleepStep>(); 91 92 var serviceProvider = services.BuildServiceProvider(); 93 94 //config logging 95 var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); 96 loggerFactory.AddProvider(new DebugLoggerProvider()); 97 98 return serviceProvider; 99 } 100 101 private void startButton_Click(object sender, RoutedEventArgs e) 102 { 103 StartWorkflow(); 104 } 105 106 private void stopButton_Click(object sender, RoutedEventArgs e) 107 { 108 StopWorkflow(); 109 } 110 } 111 }
就这样一个简单的Workflow Core例子就完成了,总体来说,还是很简单,清晰的。
以上是关于workflow-core 简介的主要内容,如果未能解决你的问题,请参考以下文章
一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core
Android 逆向类加载器 ClassLoader ( 类加载器源码简介 | BaseDexClassLoader | DexClassLoader | PathClassLoader )(代码片段
Android 逆向Linux 文件权限 ( Linux 权限简介 | 系统权限 | 用户权限 | 匿名用户权限 | 读 | 写 | 执行 | 更改组 | 更改用户 | 粘滞 )(代码片段
SpringCloud系列十一:SpringCloudStream(SpringCloudStream 简介创建消息生产者创建消息消费者自定义消息通道分组与持久化设置 RoutingKey)(代码片段
C#-WebForm-★内置对象简介★Request-获取请求对象Response相应请求对象Session全局变量(私有)Cookie全局变量(私有)Application全局公共变量Vi(代码片段