ワークフローの検証と実行
最後に作成したワークフローを実行する機能を記述します。実際に作成したワークフローの実行に必須ではありませんが、事前にワークフローの検証を行っておくべきかと思います。設定誤りなどが存在する状態でワークフローを実行した場合は例外が発生しますので、それを防ぐ意味合いでも事前の検証は有効です。
編集しているワークフローでは何かしらのエラーがあるアクティビティに対して、赤い「!」マークが表示されるようになっています。ただしあくまでもこの表示はデザイナ上だけであり、アプリケーション側ではそのままですと検知できません。発生しているエラーすべてを検知するにはActivityValidationServicesクラスを利用します。
Dim resultID As String = "" Dim rootActivity As Activity = Nothing '現在のワークフロー情報を取得 Dim mdlService = designer.Context.Services.GetService(Of ModelService)() Dim debugTree = TryCast(mdlService.Root.GetCurrentValue(), IDebuggableWorkflowTree) If (debugTree IsNot Nothing) Then rootActivity = debugTree.GetWorkflowRoot() Else rootActivity = mdlService.Root.GetCurrentValue() End If ‘ワークフローの検証実施 Dim validError = ActivityValidationServices.Validate(rootActivity) ‘検知したエラーが発生している先頭のアクティビティIDを取得 If validError.Errors.Count > 0 Then resultID = validError.Errors(validError.Errors.Count - 1).Id End If
var resultID = "";
Activity rootActivity = null;
//現在のワークフロー情報を取得
var mdlService = designer.Context.Services.GetService();
var debugTree = (IDebuggableWorkflowTree)mdlService.Root.GetCurrentValue();
if (debugTree != null) {
rootActivity = debugTree.GetWorkflowRoot();
} else {
rootActivity = (Activity)mdlService.Root.GetCurrentValue();
}
//ワークフローの検証実施
var validError = ActivityValidationServices.Validate(rootActivity);
//検知したエラーが発生している先頭のアクティビティIDを取得
if (validError.Errors.Count > 0) {
resultID = validError.Errors(validError.Errors.Count - 1).Id;
}
ActivityValidationServicesクラスを利用してワークフローの検証を行う際には、対象となるワークフローの構造情報が必要です。それを行っているのがModelServiceクラスを利用している前半の部分となります。後半部分は、前半で取得した構造情報をもとにActivityValidationServicesによる検証を行っています。検証結果はValidationResultsコレクションで返却され、発生しているすべてのエラー情報が収納されています。この内容を用いて、発生しているエラー情報を一覧にして表示するといったことが可能です。
なお、WorkflowDesigner.IsInErroStateプロパティという、エラーが発生しているかどうか判断できそうなプロパティがありますが、残念ながら思うように動作していないので利用することができません。
検証に利用するもう一つのサービスとしてValidationServiceがあります。こちらはActivityValidationServicesと異なり、ワークフローデザイナー上で編集しているワークフローの検証を行うためのサービスで、検証結果を取得するなどは行えません。どのような場面で利用するかというと、ワークフローデザイナーにワークフローを読み込ませた直後やプログラム側でワークフローを操作した直後などであり、ワークフローデザイナー以外からワークフローを操作した場合に明示的に検証を行い、ワークフローデザイナーに反映させるためのものとなっています。
ワークフローデザイナーに読み込ませたまでの状態では上図のとおりになります。エラー表示が行われていないのが確認できます。
こちらがワークフローデザイナーに読み込ませた後にValidationServiceを利用して検証を行った状態です。アクティビティの右上に「!」と赤くエラー表示されているのが確認できます。この時のコードは次のようになっています。
Dim meta = New DesignerMetadata
meta.Register()
Dim designer = New WorkflowDesigner
Dim seq = New Sequence
seq.Activities.Add(New Assign())
designer.Load(New ActivityBuilder With {.Implementation = seq})
'ValidationService による検証
Dim vsv = designer.Context.Services.GetService(Of ValidationService)()
vsv.ValidateWorkflow()
Content = designer.View
var meta = new DesignerMetadata();
meta.Register();
var designer = new WorkflowDesigner();
var seq = new Sequence();
seq.Activities.Add(new Assign());
designer.Load(new ActivityBuilder {Implementation = seq});
//ValidationService による検証
var vsv = designer.Context.Services.GetService();
vsv.ValidateWorkflow();
Content = designer.View;
検証が終われば次は実行です。ワークフローデザイナーを利用して編集したものを実行する方法はいろいろな種類がありますが、ここでは最も簡単に行う方法として、ワークフローを一度保存しそれを実行する方法を紹介します。
‘ワークフローの保存
wfDesign.Save("test.xaml")
'保存したワークフローの取得
Dim wfFile = ActivityXamlServices.Load("test.xaml")
'保存したワークフローをメタデータに取り込み
WorkflowInspectionServices.CacheMetadata(wfFile)
Dim wfInv As New WorkflowInvoker(wfFile)
wfInv.Invoke()
//適当なファイルに保存
wfDesign.Save("d:\test.xaml");
//保存したファイルよりワークフローを読み込み
var wfFile = ActivityXamlServices.Load("d:\test.xaml");
//読み込んだワークフローのメタデータを登録
WorkflowInspectionServices.CacheMetadata(wfFile);
//ワークフローの実行
var wfInv = new WorkflowInvoker(wfFile);
wfInv.Invoke();
WorkflowDesigner.Saveメソッドや前述した方法を用いて、xamlファイルとしてワークフローを保存します。保存したワークフローをActivityXamlServicesクラスのLoadメソッドを用いて読み込ませ、WorkflowInspectionServices.CacheMetadataメソッドでメタデータへ登録を行います。そうすることでWorkflowInvokerクラスなどを利用し、ワークフローの実行を行うことができます。
まとめ
WF4では標準提供されるWorkflowDesignerクラスやToolboxControlを利用することで、非常に簡易にワークフローデザイナーの機能を利用することが可能です。実行、保存、検証など、ワークフローアプリケーションに必要な機能も多くのクラスが提供されており、Visual Studio環境と同等のものを作成することができます。
次回予定
次回はWF4を利用するのに適しているケースをもとに、利用例を紹介する予定です。どのような場面がWF4の特性を生かしやすいのか、またWF技術のこれからについて紹介させていただく予定です。


