vlambda博客
学习文章列表

一个适合于.NET Core的超轻量级工作流引擎:Workflow-Core

 最近想做一个OA相关的网站开发,一直都听说有workflow的东西,之前也断断续续学习过 Workflow Foundation 4.0,还是没有搞明白到底能够用它做什么

 但还是觉得workflow在某种情形下应该可以适用,虽然还没有答案,网上搜楼了一通,发现一个workflow-core的东西,觉得挺有意思,遂停下来,琢磨一下,现分享与大家。

 

 * 简介

workflow core的GitHub主页

https://github.com/danielgerlag/workflow-core

如主页上介绍的,workflow core作为一个轻量级workflow引擎,可以嵌入到项目中,其底层是用.net standard 2.0开发,可以用来追踪长时间运行的任务状态,功能也比较强大,支持插件形式持久化,和多节点并行处理,貌似很牛。并且目前有给一个 Conductor 项目,就是使用workflow core作为内核的workflow服务器(原来运行workflow,需要单独的一个服务器啊),Conductor这里就不展开了。workflow core支持fluent语法,写起来也非常美观,虽然没有WF那样有图形化的操作界面,但感觉代码比较干净。

* 示例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),这个函数中完成所需的工作

public class HelloWorld : StepBody { private ILogger logger;
public HelloWorld(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<HelloWorld>(); }
public override ExecutionResult Run(IStepExecutionContext context) { Console.WriteLine("Hello world, workflow"); logger.LogInformation("Helloworld workflow");
return ExecutionResult.Next(); } }

public class GoodbyeWorld : StepBody { private ILogger logger;
public GoodbyeWorld(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger<GoodbyeWorld>(); }
public override ExecutionResult Run(IStepExecutionContext context) { Console.WriteLine("Workflow, Goodbye"); logger.LogInformation("Goodbye workflow");
return ExecutionResult.Next(); } }
public class SleepStep : StepBody { private ILogger logger;
public SleepStep(ILoggerFactory loggerFactory) { logger = loggerFactory.CreateLogger("SleepStep"); }
public override ExecutionResult Run(IStepExecutionContext context) { Thread.Sleep(1000);
logger.LogInformation("Sleeped");
return ExecutionResult.Next(); } }

2. 构建workflow,实现IWorkflow接口,每个workflow有一个Id和一个Version,标明这个workflow的身份,这里通过两种方法构建了HelloWorkflow

 public class HelloWorkflow : IWorkflow { public string Id => "HelloWorkflow";
public int Version => 1;
public void Build(IWorkflowBuilder<object> builder) { builder.StartWith(context => { Console.WriteLine("Hello world"); return ExecutionResult.Next(); }) .Then(context => { Thread.Sleep(500); Console.WriteLine("sleeped"); return ExecutionResult.Next(); }) .Then(context => { Console.WriteLine("Goodbye world"); return ExecutionResult.Next(); }); } }
public class HelloWorkflow2 : IWorkflow { public string Id => "HelloWorkflow";
public int Version => 2;
public void Build(IWorkflowBuilder<object> builder) { builder.StartWith<HelloWorld>() .Then<SleepStep>() .Then<GoodbyeWorld>(); } }

3. 万事俱备,准备让workflow运行起来。第一步当然是需要搭建service,Workflow Core通过Injection命名空间的ServiceCollection添加了Workflow相关的服务,对于有参数的StepBody,需要先通过service的AddTransient函数注册,这样才能正确的构造对象

/// <summary> /// 配置workflow /// </summary> /// <returns></returns> private IServiceProvider ConfigureServices() { //setup dependency injection IServiceCollection services = new ServiceCollection(); services.AddLogging(); services.AddWorkflow(); //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow"));
// 这些个构造函数带参数的,需要添加到transient中 services.AddTransient<HelloWorld>(); services.AddTransient<GoodbyeWorld>(); services.AddTransient<SleepStep>();
var serviceProvider = services.BuildServiceProvider();
//config logging var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); loggerFactory.AddProvider(new DebugLoggerProvider());
return serviceProvider; }

接下来,启动workflow 主机,并启动一次workflow,将整个窗体代码贴一下,这样比较清晰

using Microsoft.Extensions.DependencyInjection;using Microsoft.Extensions.Logging;using Microsoft.Extensions.Logging.Console;using Microsoft.Extensions.Logging.Debug;using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Navigation;using System.Windows.Shapes;using WorkflowCore.Interface;using WorkflowCore.Services;using WorkFlowCoreTest.MyWorkflow;
namespace WorkFlowCoreTest{ /// <summary> /// Interaction logic for MainWindow.xaml /// </summary> public partial class MainWindow : Window { IServiceProvider serviceProvider = null; bool serviceStarted = false;
public MainWindow() { InitializeComponent(); }
private void StartWorkflow() {
if (serviceProvider == null) { serviceProvider = ConfigureServices(); var host1 = serviceProvider.GetService<IWorkflowHost>();
host1.RegisterWorkflow<HelloWorkflow>(); host1.RegisterWorkflow<HelloWorkflow2>(); }

var host = serviceProvider.GetService<IWorkflowHost>(); var wd = host.Registry.GetDefinition("HelloWorkflow");
// 如果host启动了,不能再次启动,但没有判断方法 if (!serviceStarted) { host.Start(); serviceStarted = true; }

// 启动workflow工作流 host.StartWorkflow("HelloWorkflow", 1, data: null); // //host.StartWorkflow("HelloWorkflow");//, 2, data: null, 默认会启用版本高的 }
private void StopWorkflow() { var host = serviceProvider.GetService<IWorkflowHost>();
host.Stop(); serviceStarted = false; }
/// <summary> /// 配置workflow /// </summary> /// <returns></returns> private IServiceProvider ConfigureServices() { //setup dependency injection IServiceCollection services = new ServiceCollection(); services.AddLogging(); services.AddWorkflow(); //services.AddWorkflow(x => x.UseMongoDB(@"mongodb://localhost:27017", "workflow"));
// 这些个构造函数带参数的,需要添加到transient中 services.AddTransient<HelloWorld>(); services.AddTransient<GoodbyeWorld>(); services.AddTransient<SleepStep>();
var serviceProvider = services.BuildServiceProvider();
//config logging var loggerFactory = serviceProvider.GetService<ILoggerFactory>(); loggerFactory.AddProvider(new DebugLoggerProvider());
return serviceProvider; }
private void startButton_Click(object sender, RoutedEventArgs e) { StartWorkflow(); }
private void stopButton_Click(object sender, RoutedEventArgs e) { StopWorkflow(); } }}

就这样一个简单的Workflow Core例子就完成了,总体来说,还是很简单,清晰的。


出处:

https://www.cnblogs.com/keep-study-to-die/p/12001408.html



支持小微:

腾讯云 新年活动!玩服务器的可以搞搞,老客户也可以参加!

轻量服务器  2核4G8M80G 222元/3年  

爆款1核2G云服务器首年38元  

链接:https://curl.qcloud.com/bR8ycXZa


右下角,您点一下在看图片

小微工资涨1毛

商务合作QQ:185601686