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例子就完成了,總體來說,還是很簡單,清晰的。

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM