• workflow-core 简介


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

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

     * 简介

    workflow core的GitHub主页

    如主页上介绍的,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     }
    View Code

    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     }
    HelloWorkflow

    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         }
    构建Service

    接下来,启动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 }
    View Code

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

  • 相关阅读:
    第一篇 HTML5打包APP之VMware15安装MAC(MAC OS 10.13)(OS X 10.14)原版可升级最新可解锁macOS Unlocker3.0(OS X 10.13)
    phpcms V9 网站域名变更后,刷新所有缓存后,栏目链接总是改不过
    ECShop——给商品详情页添加字段
    java webcontroller访问时报415错误
    SVN设置忽略上传属性
    Eclipse的Servers视图中无法添加Tomcat6/Tomcat7
    jquery $.each遍历json数组方法
    jquery 中json数组的操作 增删改
    JQuery获取input type="text"中的值的各种方式
    eclipse下把所有的文件都转换为UTF-8的方法
  • 原文地址:https://www.cnblogs.com/keep-study-to-die/p/12001408.html
Copyright © 2020-2023  润新知