サンプル1~シーケンシャル ワークフロー
では、早速ワークフローを使ったサンプルを実装してみましょう。最初はシンプルなシーケンシャル ワークフローをデザインし、スタンドアロンアプリケーションでホスティングします。
今回は購入申請アプリケーションで、入力された申請内容の条件を見て、申請を許可するか却下するかを判断する、というワークフローを作成します。
申請内容は次のようなクラスで、金額・申請者名・申請品目のみを保持するものとしましょう。
public class ApplicationForm { int price; public int Price //金額 { get { return price; } set { price = value; } } string applicantName; public string ApplicantName //申請者名 { get { return applicantName; } set { applicantName = value; } } string productName; public string ProductName //購入品目 { get { return productName; } set { productName = value; } } }
このクラスのPrice
プロパティが一定額未満であれば購入許可、一定額以上であれば拒否、というシンプルなワークフローです。
[ファイル]-[新規作成]-[プロジェクト]を選択し、[Visual C#]-[Workflow]-[シーケンシャル ワークフロー コンソール アプリケーション]を選択してプロジェクトを作成します。
ここではSeqWFTestというプロジェクトを作成しました。
プロジェクト作成後、ワークフローのひな形としてWorkflow1.csが作成され、デザイン画面が表示されます。
シーケンシャル ワークフローは前述の通り、ワークフロー開始から終了までアクティビティが順に実行されて流れていくワークフローです。この画面のがワークフロー開始を、がワークフロー終了を表しています。
では、ワークフローをデザインしてみましょう。
アクティビティの配置
まずツールボックスからIfElseアクティビティをドラッグ&ドロップでワークフロー開始と終了の間に貼り付けます。
IfElseアクティビティは、前述の通りコンポジット アクティビティで、条件分岐した後に実行すべきアクティビティを持つことができます。今回はプログラムを直接実行するCodeアクティビティをそれぞれに配置してみましょう。
以上でアクティビティの配置は完了です。次に条件とコードの実装に進んでいきましょう。
ワークフローのパラメータ指定
条件分岐の設定をする前に、[プロジェクト]-[新しい項目の追加]から[クラス]を選択し、先ほどのApplicationForm
クラスをプロジェクトに追加しましょう。
次にワークフローに、パラメータである購入申請を受け取るためのプロパティを追加します。
ソリューション エクスプローラの「Workflow1.cs」を右クリックし、[コードの表示]を選択して、以下のコードを追加します。
private ApplicationForm form; public ApplicationForm Form { get { return form; } set { form = value; } }
IfElseアクティビティの条件設定
次に条件設定です。貼り付けたIfElseアクティビティの左下のifElseBranchActivity1をクリックし、右下のプロパティペインでCondition
プロパティを設定します。
ソースコードによる条件指定も可能ですが、今回は[宣言型のルール条件]を選択しましょう。Condition
プロパティの配下にConditionName
プロパティが作成されますので、右端の[...]ボタンをクリックします。
[条件の選択]画面で[新規作成(N)]ボタンをクリックします。
[ルール条件エディタ]画面で実際の条件を指定します。
入力された購入申請の価格が5000未満かどうかという条件分岐にしますので、
form.Price < 5000
という条件を入力します。入力の際に、IntelliSenseが働くことに注目してください。
[OK]ボタンを押し、[条件の選択]画面で条件を確認してください。
Codeアクティビティへのコード実装
以上で条件分岐が設定できたので、Codeアクティビティで条件分岐後のコードを書きましょう。Codeアクティビティをダブルクリックすると、実行するコードを記述するためのハンドラが自動生成されます。
ここでは次のようにハンドラを記述します。
private void codeActivity1_ExecuteCode(object sender, EventArgs e) { //条件真の場合 Console.WriteLine( string.Format("{0}さんの{1}購入申請は許可されました。", form.ApplicantName, form.ProductName)); } private void codeActivity2_ExecuteCode(object sender, EventArgs e) { //条件偽の場合 Console.WriteLine(string.Format( "{0}さんの{1}購入申請は却下されました。", form.ApplicantName, form.ProductName)); }
条件を満たす場合、満たさない場合それぞれにメッセージを出力します。
以上でワークフロー側の実装は完了です。
Mainメソッドからのワークフロー呼び出し
次に「Program.cs」を開き、Main
メソッドの内容を確認しましょう。
static void Main(string[] args) { using(WorkflowRuntime workflowRuntime = new WorkflowRuntime()) { AutoResetEvent waitHandle = new AutoResetEvent(false); workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();}; workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e) { Console.WriteLine(e.Exception.Message); waitHandle.Set(); }; WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(SeqWFTest.Workflow1)); instance.Start(); waitHandle.WaitOne(); } }
ここで重要なのはワークフローの生成を司るWorkflowRuntime
クラスと、ワークフローの実体を表すWorkflowInstance
クラスです。
WorkflowRuntime
クラスはワークフローを実行するためのランタイムで、1つのプロセスに付き1つだけインスタンスを生成し、その上でワークフローを実行します。
続いていくつかのイベントハンドラ登録を行った後、WorkflowRuntime#createWorkflow
メソッドからWorkflowInstance
インスタンスを生成しています。引数にSeqWFTest.Workflow1
クラスの型を指定することで、実際に実行するワークフローを特定します。その後Start
メソッドで実行を開始します。
以上はワークフロー実行時にパラメータを渡さない場合のコードです。今回は購入申請をパラメータとして渡しますので、コードの書き換えを行いましょう。
CreateWorkflow
メソッドでインスタンス生成を行っている部分を、次のように書き換えます。
//購入申請インスタンス生成 ApplicationForm form = new ApplicationForm(); form.ApplicantName = "土井"; form.Price = 3200; form.ProductName = "参考文献"; //パラメータとなるDictionaryクラスを生成 Dictionary<string, object> properties = new Dictionary<string, object>(); properties.Add("Form", form); //ワークフロー生成時にパラメータも渡す WorkflowInstance instance = workflowRuntime.CreateWorkflow( typeof(SeqWFTest.Workflow1),properties); instance.Start(); waitHandle.WaitOne(); Console.ReadKey(); //キー入力待ち
ApplicationForm
クラスに申請情報を入力し、それをDictionary
型のproperties
変数にいったん格納します。その際にキーとして指定した文字列"Form"
は、ワークフローに作成したプロパティ名と合わせる必要があります。パラメータを詰めたproperties
変数をCreateWorkflow
メソッドの2番目の引数として指定します。ここで、内部的にはDictionary
型のキーと値が、ワークフローのプロパティ名とプロパティ値とみなされ、プロパティが設定されます。
この場合は作成した申請情報がForm
プロパティに設定された上でワークフローが生成されることになります。
ワークフローの実行
では、[F5]キーを押して実行してみましょう。
今回はPrice
プロパティの値が3200ですので、条件(Priceが5000未満)を満たし、購入申請は許可されます。
ワークフローのデザイン/実行が非常にシンプルなことがご理解いただけたかと思います。