管理者が業務で本技術を使用するため、この記事を転載します。Workflow の概要とその活用方法について皆さんと共有します。
記事本文は以下の通りです。
最近、OA 関連の Web サイト開発をしたいと考えており、以前から 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 のようにグラフィカルな操作画面はありませんが、コードはすっきりしていると感じます。
- 余談: .NET Standard 2.0 の概要
最初は .NET Standard 2.0 が何かよくわかっていませんでした。この記事で比較的明確に説明されています: .Net Standard と .NET Framework の関係、また .NET Core 2.0 はあなたの最良の選択か。Microsoft は .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。このパッケージをインストールすると、デフォルトで一連の依存パッケージもインストールされます。
バージョンの関係か、さらに2つのパッケージをインストールする必要があるかもしれません: Microsoft.Extensions.Logging と Microsoft.Extensions.Logging.Debug。これで Sample 01 に従ってコードを書き始めることができます。

Sample01 は helloworld で、以下のいくつかの部分で構成されています:
- 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();
}
}
- workflow の構築: IWorkflow インターフェースを実装します。各 workflow には Id と Version があり、その workflow の識別子となります。ここでは2つの方法で 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>();
}
}
- 準備が整ったので、workflow を実行させてみましょう。まずはサービスを構築する必要があります。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 ホストを起動し、1回 workflow を起動します。フォーム全体のコードを以下に貼り付けて、わかりやすくします。
using Microsoft.Extensions.DependencyInjection;
using System.Windows;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Debug;
using WorkflowCore.Interface;
namespace WorkflowTest;
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 のサンプルが完成しました。全体的に非常にシンプルでわかりやすいです。
本記事は転載です。
著者: Jimmy.Tang
原文タイトル: .NET Core に適した超軽量ワークフローエンジン: Workflow-Core
原文リンク: https://www.cnblogs.com/keep-study-to-die/p/12001408.html
管理者注: 文中のコードでは多くのパッケージが参照されていますが、原文ではすべて説明されていません。管理者がテストした際にパッケージを補完しました。テストコードはこちら: https://github.com/dotnet9/TerminalMACS.ManagerForWPF/tree/master/src/Demo/WorkflowTest