「Windows Workflow Foundation ルール エンジン入門」

 

Jurgen Willis
Microsoft Corporation

2006 年 2 月

適用対象:
   Windows Workflow Foundation (WF) ベータ 2
   Visual Studio 2005

概要: この記事では、Windows Workflow Foundation (WF) のルール エンジン機能の概要について説明します。 WF での条件と RuleSet の使用方法について説明し、前方チェーンや追跡、トレースなど、ルールのコレクションの動作について説明します。 (18ページ印刷)

メモ この記事はベータ 2 を使用して記述されており、今後、Windows Workflow Foundation の新しいバージョンで動作させるために、いくつかの変更を加える必要がある場合があります。

内容

はじめに
Windows Workflow Foundation のルールの概要
ルールの評価
前方チェーン
フォワード チェーン コントロール
モデリングに関するその他のディスカッション
追跡とトレース
まとめ
詳細情報

はじめに

Windows Workflow Foundation (WF) の可用性により、Microsoft は WinFX 開発者プラットフォームに新しいルール機能を導入しています。 これらの機能は、アクティビティの実行動作を促進する単純な条件から、フル機能の順方向チェーン ルール エンジンによって実行される複雑な RuleSet までを拡張します。

ルール機能を使用すると、ビジネス プロセス全体の範囲内で、アプリケーション ロジックの単位を宣言的にモデリングできます。 ルール エンジン テクノロジのサンプル シナリオは、注文の検証、価格計算、昇格の適用、例外プロセス管理、要求の判断と管理です。

このテクノロジを開発する上で重要な目的は、真に統合されたワークフローとルールのエクスペリエンスを提供することです。 業界全体で、ルールとワークフローは、通常、異なるベンダーによって提供される、非常に異なるテクノロジでした。 サードパーティのルール エンジンは、多くの場合、ワークフローおよびビジネス プロセス管理 (BPM) プロバイダーによって埋め込まれたり統合されたりしますが、開発者と管理のエクスペリエンスは明らかにシームレスなものではありません。

WF では、開発者がワークフローの任意の時点でルールを簡単に組み込むことができるように、ワークフローとルール モデリングの間でシームレスな開発者エクスペリエンスを提供することに重点を置いてきました。 開発者は、ワークフロー モデル、ルール、またはコードでロジックをモデル化するかどうかを決定できます。これらの決定の統合への影響を心配する必要はありません。 ただし、これは、ワークフローの範囲外でルールを実行する機能を犠牲にすることなく実現されています。

2 つ目の重要な目的は、開発者がルールの定義に使用する簡単なモデルを提供することです。 ルール技術はこれまで、多くの場合、ルールの専門家の非常に専門的なグループによって使用されるニッチな技術でした。 ツールの改善により、ルールを使用する個人のセットが広がっている一方で、モデルでは多くの場合、ユーザーが基になるエンジンの実装メカニズムに精通しすぎている必要があります。 プラットフォームにルール機能を提供する際に、幅広い .NET 開発者コミュニティと最終的に非開発者がアプローチできるモデルを選択しました。 あらゆるテクノロジと同様に、常に特定のレベルのドメインの専門知識がありますが、すべての .NET 開発者がルール モデルを迅速に立ち上げ、アプリケーションに簡単に組み込むことができることが目標です。

WFは、アプローチ可能なモデルを提供するだけでなく、複雑なルールシナリオをサポートする強力な評価エンジンを提供し、前方チェーン評価と正確な評価制御を要求します。 これは、多数の拡張ポイントを提供する方法で提供され、開発者はプラットフォーム上に構築し、さまざまなシナリオをサポートするルール機能を提供できます。

このドキュメントでは、WF で提供されるルール機能の技術的な概要と、使用可能な機能とその使用方法の概要について説明します。 このドキュメントの最後には、WF のルール機能について学習するために使用できる追加のリソースの一覧が記載されています。

Windows Workflow Foundation のルールの概要

ルール テクノロジは、WF の 2 つの重要な方法で公開されます。アクティビティの条件として、またポリシー アクティビティの前方チェーン RuleSet として公開されます。 前方チェーンについては、ドキュメントの後半で説明します。簡単に言えば、あるルールのアクションが他の依存ルールを再評価する能力を指します。

アクティビティの条件

条件は、WF に付属する次の 4 つのアクティビティで使用されます。

  • IfElseBranch
  • While
  • レプリケーター
  • ConditionedActivityGroup (CAG)

条件は、これらのアクティビティの実行動作を促進するために使用されます。たとえば、特定の IfElseBranch が実行されるかどうかを判断します。 条件は 、CodeConditions として指定できます。このコードの横にハンドラーが構成されます。また、 RuleConditionReference として指定することもできます。 RuleConditionReference は、ワークフロー プロジェクトのワークフローに関連付けられた .rules ファイル内の RuleCondition 定義を指します。 Visual Studio のエクスペリエンスは、図 1 に示されています。

Aa480193.intwf_fndrlseng01(en-us,MSDN.10).gif

図 1. WF ルール条件の作成

ルール条件の追加

IfElse アクティビティ内にある IfElseBranch アクティビティにルール条件を追加する手順を次に示します。

  1. 条件を持つアクティビティが選択されている場合 (IfElseBranch アクティビティが表示されている場合と同様)、 Condition プロパティが [プロパティ] グリッドに表示されます。
  2. Condition プロパティのドロップダウンを使用すると、ユーザーは CodeCondition または RuleConditionReference を選択できます。
  3. RuleConditionReference が選択されている場合は、Condition プロパティを展開して ConditionName プロパティと Expression プロパティ表示できます。
  4. 条件名を指定すると、 Expression プロパティの省略記号が選択され、ルール条件エディターが起動します。 このエディターを使用すると、開発者は Intellisense のようなサポートを使用して、テキスト形式で条件を入力できます。 テキストは、 RuleCondition の関連付けられたオブジェクト モデル表現に解析されます。
  5. [OK] を選択すると、RuleCondition 定義が、プロジェクトに<追加される WorkflowName.rules> ファイルにシリアル化されます。

ワークフローのフィールドまたはプロパティを参照するには、 これを エディターに入力します。 ドットを入力すると、ワークフローでメンバーを選択できる Intellisense のようなメニューが表示されます (メンバーを直接入力することもできます)。 入れ子になった呼び出しも行うことができます。たとえば、 this.order.Total です。 参照される型に対して静的メソッドを呼び出す場合は、コードの場合と同様に、クラス名に続けてメソッド名を入力します。

式は、次の関係演算子でサポートされています。

  • Equal ("==" または "=")
  • より大きい ("">)
  • 以上 (">=")
  • より小さい ("<")
  • 以下 ("<=")

さらに、次の算術演算子を使用することもできます。

  • 追加 ("+")
  • 減算 ("-")
  • 乗算 ("*")
  • 除算 ("/")
  • 剰余 ("MOD")

式は、次の演算子を使用して結合または否定できます。

  • AND ("AND", "&&")
  • OR ("OR", "||")
  • NOT ("NOT", "!")
  • ビットごとの および (""&)
  • ビットごとのまたは ("|")

開発者がコード条件の代わりにルール条件を使用する主な理由は、ルール条件がモデルの一部になり、ワークフロー インスタンスの実行時に動的に更新できることです。 ルール条件の 2 つ目の利点は、モデルの一部として、より高度なツールをモデルの上に構築して、追加のオーサリング エクスペリエンス、依存関係管理、クロス条件分析などを提供できることです。

ポリシー アクティビティ

Policy アクティビティは、RuleSet の定義と実行をカプセル化します。 RuleSet は、一連の実行セマンティクスを持つルールのコレクションです。 ルールは、ワークフロー メンバーに対して動作する If-Then-Else 式です。 このエクスペリエンスは図 2 に示されており、ルールの条件に似ています。

Aa480193.intwf_fndrlseng02(en-us,MSDN.10).gif

図 2. WF RuleSet の作成

ポリシー アクティビティの追加

ポリシー アクティビティのルールセットを構成するには、次の手順に従います。

  1. ツールボックスからワークフロー デザイナーにポリシー アクティビティをドラッグします。
  2. RuleSetReference では、RuleSet の名前が指定されます。
  3. [ RuleSet 定義 ] フィールドで省略記号を選択すると、ルール セット エディターが起動します。
  4. エディターには、リスト ボックスにルールのコレクションが表示されます。
  5. 特定のルールを選択すると、その条件、次のアクション、Else アクション、および追加のプロパティのセットが表示されます。
  6. ルール条件エディターと同様に、Condition、Then アクション、Else アクションがテキストとして入力され、関連付けられたオブジェクト モデル表現に解析されます。ルールは、ワークフロー上のメンバーに対して構築されます。
  7. [OK] を選択すると、RuleSet がワークフローに関連付けられている .rules ファイルにシリアル化されます。

RuleSetReference プロパティで省略記号を選択するとエディターが起動し、図 3 に示すように、ユーザーは既存の RuleSet を選択したり、RuleSet を追加/名前変更/削除したりできます。

Aa480193.intwf_fndrlseng03(en-us,MSDN.10).gifAa480193.intwf_fndrlseng03

図 3: WF RuleSet ブラウザー

ルールの評価

RuleSet 内の各ルールには、既定値が 0 の優先度値があります。 RuleSet 内のルールは、優先順位の値で並べ替えられたコレクションと見なすことができます。 WF ルール エバリュエーターは、ルールを個別に評価し、ルールの条件評価の結果に基づいてルールのアクションを実行します。

評価メカニズムは、次の手順で概念的に説明できます。

  1. 最初に、アクティブなルールのリストを取得します。
  2. 優先順位の最も高いルールを見つけます。
  3. そのルールを評価し、Then/Else アクションを適切に実行します。
  4. ルールのアクションによって、リスト内の以前のルールで使用されているフィールド/プロパティ (優先度の高いルール) が更新された場合は、その前のルールを再評価し、必要に応じてアクションを実行します。 特定の依存関係を持つルールのみが再評価されることに注意してください。
  5. RuleSet 内のすべてのルールが評価されるまで、プロセスを続行します。

単純な例を見てみましょう。 次の RuleSet があり、 AB などがワークフロー上のデータを表しているとします。

Rule4 (Priority = 4)

IF A = 15
THEN B = 5

Rule3 (P=3)

IF C = 5
THEN B = 10

Rule2 (P=2)

IF D = 2
THEN A = 15

Rule1 (P=1)

IF B = 5
THEN E = 7

次のような入力データがあるとします。

  • A = 0
  • B = 0
  • C = 5
  • D = 2
  • E = 0

評価は次のように続行されます。

  • Rule4 が評価されます。 false と評価され、 Else アクションがないため、アクションは実行されません。
  • Rule3 は true に評価され、そのアクションが実行され、 B = 10 が設定されます。 Rule4 は B の値に依存しないため、評価は Rule2 に進みます。
  • Rule2 は true に評価され、そのアクションが実行され、 A = 15 が設定されます。
  • Rule4 はその条件で A の値を使用するため、再評価されます。 true に評価され、そのアクションが実行され、B = 5 が設定されます。Rule3 と Rule2 は、条件が A の値に依存しないため、再評価されません。前の規則は B の値に依存しないため、評価は Rule1 に進みます。
  • Rule1 は true に評価され、そのアクションが実行され、 E = 7 が設定されます。

これで、結果のデータ セットは次のようになります。

  • A = 15
  • B = 5
  • C = 5
  • D = 2
  • E = 7

順方向チェーン

前述のように、チェーンは、ルール間で識別された依存関係に基づいています。具体的には、ルールのアクションと他のルールの条件間の依存関係です。 これらの依存関係は、次の 3 つの方法のいずれかで識別または宣言できます。

  • 暗黙
  • 属性ベース
  • 明示

暗黙

暗黙的な依存関係は、エンジンによって自動的に識別されます。 RuleSet が最初に実行されると、各ルールが分析され、その条件で読み取られ、アクションで書き込まれるフィールド/プロパティが評価されます。 これは、条件内の式とアクション内の ステートメントをウォークすることによって行われます。 たとえば、次の規則を想定します。

規則 1

IF this.subtotal > 10000
THEN this.discount = .05

規則 2

IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

エンジンはルールを評価し、ルール 1 が小計フィールドを読み取り、割引フィールドに書き込むことを識別します。 ルール 2 では、割引フィールドと小計フィールドを読み取り、合計フィールドに書き込みます。 したがって、規則 2 は規則 1 に依存します。その結果、ルール 1 が Then アクションを実行するたびに、エンジンによってルール 2 が評価または再評価されるようになります。

依存関係はリーフ ノード レベルで識別されることに注意してください。 次の RuleSet を実行します。

規則 1

IF this.order.Subtotal > 10000
THEN this.order.Discount= .05

規則 2

IF this.order.Discount > 0
THEN this.order.Total = (1-this.order.Discount) * this.order.Subtotal

規則 3

IF this.order.CustomerType = "Residential"
THEN ...

ルール 1 と 2 の間で依存関係が引き続き識別されます。 ただし、ルール 3 は、 どちらも CustomerType プロパティを更新しないため、ルール 1 または 2 には依存しません。 つまり、依存関係は Order オブジェクト自体ではなく、CustomerType プロパティのレベルで識別されます。

WF は、暗黙的なチェーンを使用して、ユーザーに必要なチェーンの大部分を行います。そのため、ユーザーは更新プログラムを明示的にモデル化する必要はありません。実際には、ほとんどの場合、チェーンやチェーンの必要性を知らなくてもかまいません。 これにより、複雑な RuleSets のモデリングがほとんどのユーザーにとってより簡単になり、エンジンの強力で、ほとんど非表示の機能をチェーンするという概念が得られます。 ただし、より複雑で具体的なシナリオでは、属性ベースと明示的なチェーンを駆動するための他の 2 つのメカニズムが用意されています。

属性ベース

ルール内でのメソッド呼び出しでは、発生する読み取りと書き込みを決定的に評価することが難しくなります。 この問題に対処するために、WF には、アクションを示すメソッドに適用できる 3 つの属性が用意されています。

  • RuleRead
  • RuleWrite
  • RuleInvoke

RuleRead 属性を持つメソッドに属性を設定すると、指定されたプロパティが読み取られたことを示します。 同様に、 RuleWrite 属性を使用して、メソッドが特定のフィールドまたはプロパティを更新することを示すことができます。 暗黙的セクションの下の最初の 2 つの規則が次のように書き換えられたとします。

規則 1

IF this.subtotal > 10000
THEN this.SetDiscount(.05)

規則 2

IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

SetDiscount メソッドは次のように属性付けできます。これにより、エンジンは、割引フィールドの使用により、ルール 2 がルール 1 に依存していることを識別できます。

[RuleWrite("discount")] 
void SetDiscount(double requestedDiscount)
{
     ...//some code that updates the discount field
}

RuleInvoke 属性を使用すると、リンクされたメソッド呼び出しによる依存関係を指定できます。 たとえば、ルールとメソッドに対して次の変更があるとします。

規則 1

IF this.subtotal > 10000
THEN this.SetDiscountWrapper(.05)

規則 2

IF this.discount > 0
THEN this.total = (1-this.discount) * this.subtotal

[RuleInvoke("SetDiscount")]
void SetDiscountWrapper(double requestedDiscount)
{
     ...
     SetDiscount(requestedDiscount);
     ...
}

[RuleWrite("discount")] 
void SetDiscount(double requestedDiscount)
{
}

ルール 2 の条件は SetDiscountWrapper を呼び出し、次に SetDiscount を呼び出し、割引フィールドに書き込みます。 RuleInvoke 属性を使用すると、この間接書き込みをエンジンで宣言して検出できます。

属性パスで参照されるフィールドまたはプロパティが、 メソッドと同じクラスのフィールドまたはプロパティを参照していることを認識することが重要です。これは、実行のために RuleSet に渡されるルート オブジェクトであるとは限りません。 たとえば、 Order クラスの属性を次に示します。

public class Order
{
     private double discount;

     public double Discount
     {
     get { return discount;}
     set { discount = value;}
     }

     [RuleWrite("Discount")] 
     void CalculateDiscount(double requestedDiscount, double weighting)
     {
...//some code that updates the discount field
     }
}

その後、次のようにワークフローでこのクラスのインスタンスを使用できます。

public class Workflow1 :  SequentialWorkflowActivity
{
     private Order discount;

     ...
}

ルール 2 を実行すると、ルール 1 が再評価されます。

規則 1

IF this.order.Discount > 5
THEN ...

規則 2

IF ...
THEN this.order.CalculateDiscount( 5.0, .7)

属性の使用に関するいくつかの追加のポイント:

  • 属性は、メソッド呼び出しのパラメーターではなく、 Owner クラスのフィールド/プロパティを指します。
  • ワイルドカードは、ルール属性でも使用できます。 たとえば、 RuleWrite("order/*") を使用して、"order" フィールドによって参照されるオブジェクトのすべてのフィールドが メソッドによって変更されることを示すことができます (この例では、メソッドは Order クラスではなくワークフロー自体にあります)。 ただし、ワイルドカードはパスの末尾でのみ使用できます。 RuleWrite("*/Discount") などの属性が無効です。
  • RuleWrite("order") などの属性を参照型と共に使用すると、参照が変更されたことを示すことができます。たとえば、変数が別の Order インスタンスを指していることを示します。 変数に対してフィールド/プロパティを使用するすべてのルールは、インスタンス参照自体をテストするすべてのルール (IF this.order == this.order2 など) に加えて、影響を受けるものと見なされます。
  • メソッド属性が指定されていない場合の既定の動作は、メソッド呼び出しはターゲット オブジェクト (メソッドが呼び出されるオブジェクト) のすべてのフィールド/プロパティを読み取ると見なされ、いずれも書き込まれないということです。 さらに、メソッドは、渡されたパラメーターから読み取ると見なされますが、いずれのパラメーターにも書き込まないと見なされます。 ルール アクションで使用する場合、Out パラメーターと ref パラメーターは に書き込まれるものと見なされます。

明示

フィールド/プロパティの依存関係を示す最後のメカニズムは、 Update ステートメントを使用することです。 Update ステートメントは、引数として、フィールドまたはプロパティへのパスを表す文字列、またはフィールド/プロパティ アクセスを表す式を受け取ります。 たとえば、次の 2 つのステートメントのいずれかを RuleSet エディターに入力して、ワークフロー上の Customer インスタンスの Name プロパティに Update ステートメントを作成できます。

Update("this/customer/Name") 

OR

Update(this.customer.Name)

Update ステートメントは、ルールが指定されたフィールド/プロパティに書き込むことを示します。 これは、ルール内のフィールド/プロパティの直接セットや、フィールド/プロパティの RuleWrite 属性を持つメソッドの呼び出しと同じ効果を持ちます。

Update コマンドでは、ワイルドカードの使用もサポートされています。 たとえば、次の Update コマンドをルールに追加できます。

Update("this/customer/*")

これにより、 条件で Customer インスタンスのプロパティを使用するすべてのルールが再評価されます。 つまり、次の 2 つのルールはそれぞれ再評価されます。

IF this.customer.ZipCode == 98052
THEN ...

IF this.customer.CreditScore < 600
THEN ...

一般に、ユーザーは、ほとんどのシナリオで明示的な Update ステートメントをモデル化する必要はありません。 暗黙的なチェーンは、ほとんどのシナリオで必要な依存関係分析とチェーン動作を提供する必要があります。 メソッド属性は、暗黙的なチェーンによって依存関係を識別できない最も一般的なシナリオをサポートする必要があります。 一般に、 Update ステートメントの使用よりも依存関係を示す場合は、メソッドの属性指定が推奨される方法です。これは、依存関係をメソッドで 1 回識別し、そのメソッドを使用する多くの異なるルールで利用できるためです。 また、ルール ライターとメソッドの実装者が異なる個人である (または作業が異なる時間に行われる) シナリオでは、メソッドの属性によって、メソッド ライター (コードを最もよく知っている) がメソッドの依存関係を識別できるようになります。

ただし、 Update ステートメントが 適切なソリューションになるシナリオがいくつかあります。たとえば、次のコードのように、ワークフロー ライターが制御しないクラスのメソッドにフィールド/プロパティが渡され、属性を設定できない場合などです。

IF ...
THEN this.customer.UpdateCreditScore(this.currentCreditScore)
     Update(this.currentCreditScore)

フォワード チェーン コントロール

前方チェーンは非常に強力な概念であり、ルール間の依存関係を定義したり、必ずしも知識がなくても、アトミックルールを RuleSets に組み立てることができます。

ただし、一部のシナリオでは、ルールライターは、チェーン動作をより詳細に制御する機能、特に発生するチェーンを制限する機能を必要とする場合があります。 これにより、ルール モデラーは次のことが可能になります。

  • 不適切な結果を生じる可能性のある、ルールの繰り返し実行を制限する。
  • パフォーマンスを向上させる。
  • ランナウェイ ループを防ぐ。

このレベルの制御は、次の 2 つのプロパティによって WF ルールで容易になります。

  • RuleSet のチェーン動作 プロパティ。
  • 各ルール の再評価動作 プロパティ。

このどちらの値も、RuleSet エディターで設定できます。

チェーン動作プロパティ

RuleSet の Chaining Behavior プロパティには、次の 3 つの可能な値があります。

  • フル チェーン
  • 明示的なチェーン
  • 逐次

[完全なチェーン] オプションが既定であり、この時点まで説明した動作が提供されます。 [明示的なチェーン] オプションは、暗黙的および属性ベースのチェーンをオフにし、明示的な Update ステートメントに対してのみチェーンを行う必要があることを規定します。 これにより、ルール ライターは、再評価の原因となるルールを完全に制御できます。 通常、これは、過剰な (または暴走する) ルールの再実行を引き起こす循環依存関係を回避したり、RuleSet の機能の完全性を提供するために不要な余分なルールの再評価を排除してパフォーマンスを向上させたりするために使用されます。

最後のオプションは シーケンシャルです。 このオプションにより、エンジンは厳密に線形的にルールを評価します。 各ルールは、優先度の順に 1 回と 1 回だけ評価されます。 優先度が高いルールは優先順位の低いルールに影響を与える可能性がありますが、チェーンが発生しないため逆は当てはまらない可能性があります。 したがって、このオプションを使用するのは、ルール間に依存関係が存在せず、優先度を明示的に割り当てるような場合です。

再評価動作プロパティ

ルールの再評価動作には、次の 2 つの値を指定できます。

  • Always (常に)
  • Never (決してしない)

Always は既定値であり、前に説明した動作を提供します。つまり、他のルールのアクションにより、チェーンに基づいてルールが常に再評価されます。 名前が示すように、この再評価をオフにしないでください。 ルールは 1 回評価されますが、以前にアクションを実行した場合は再評価されません。 つまり、ルールが以前に評価され、その結果として Then アクションまたは Else アクションを実行した場合、再評価されません。 ただし、 Then アクションまたは Else アクションで空のアクション コレクションを実行しても、ルールは実行済みとしてマークされません。

通常、このプロパティはルール レベルで使用され、独自のアクションまたはその他のルールに対してルールが持つ依存関係による無限ループを防ぎます。 たとえば、次の規則では独自の無限ループが作成され、ルールの機能要件を満たすために再評価は必要ありません。

IF this.shippingCharge < 2.5 AND this.orderValue > 100
THEN this.shippingCharge = 0

または、ルールが再評価されることを意図しているが、 OrderValue フィールドが変更された場合にのみ、ユーザーは RuleSet のチェーン動作を明示的な Update ステートメントでのみチェーンするように設定できます (その後、それらの Update ステートメントを関連するルール アクションに追加します)。 もちろん、ユーザーは ShippingCost の値がまだ 0 ではないことを確認する述語をこのルールに追加できましたが、チェーン コントロールを使用すると、ビジネス要件ではなく、評価の詳細に基づいてルールを定義する必要がありません。

Halt 関数

最後のコントロールとして、 Halt 関数をルール アクションとして追加できます (エディターの Then アクション ボックスまたは Else アクション ボックスに「Halt」と入力するだけです)。 これにより、RuleSet の実行が直ちに停止し、呼び出し元のコードに制御が戻ります。 もちろん、この関数が役立つのは、チェーン コントロールの場合だけではありません。 たとえば、特定の機能目標を持つ RuleSet では、 Halt 関数を使用して、目標に達したら実行をショートサーキットできます。

モデリングに関するその他のディスカッション

優先度ベースの実行

前のセクションで説明したように、ユーザーが RuleSet またはその RuleSet 内のルールのサブセットに対して特定の実行シーケンスを必要とする場合は、ルールの優先度フィールドを使用してこのシーケンスを正確に定義できます。 そうすることで、多くの場合、チェーンの要件が削除され、ユーザーはこれらのシナリオでチェーンをオフにすることもできます。 多くの場合、明示的な実行シーケンス処理を提供するだけで、ルールの依存関係を満たすことができることがわかりました。

ただし、WF の前方実行メカニズムには、ユーザーが実行シーケンスを定義する機能が用意されていますが、実行シーケンスを定義する必要はありません。 ほとんどの場合、前方チェーン動作では、ルールの依存関係が満たされるように、リレーションシップがエンジンによって自動的に管理されるため、ルールの優先順位を割り当てる必要がありません。

次の規則を使用します。

規則 1

IF this.Weather.Temperature < 50
THEN this.Drink.Style = "Latte"

規則 2

IF this.Drink.Style == "Latte"
THEN this.Snack.Style = "Scone"
ELSE this.Snack.Style = "Muffin"

WF では、ルール 1 の優先度を高くして、最初に実行することができます。 これにより、規則 2 が評価される前に Drink.Style が設定されます。

ただし、必要な結果を得るためにシーケンス処理は必要ありません。 ルール 2 が最初に評価されたとします。 この場合、 Drink.Stylenull であるか、別のスタイルである可能性があります。 これにより、 Snack.StyleMuffin に設定されます。 ただし、ルール 1 が実行され 、Drink.StyleLatte に設定されると、ルール 2 が再評価され、 Snack.StyleScone に設定されます。 基本的に、ユーザーにはシーケンス処理をディクテーションするオプションがありますが、多くの場合、これを行う必要はありません。

コレクション処理

シナリオによっては、コレクション内のすべての項目に対してルールを個別に評価することが必要になる場合があります。 コレクションの反復処理はさまざまな方法で行うことができますが、1 つの方法は次のようなルール パターンを使用することです。

規則 1 (優先度 = 2)

//always execute this rule once to create the enumerator
IF 1==1 
THEN this.enumerator = this.myCollection.GetEnumerator()

規則 2 (優先度 = 1)

IF this.enumerator.MoveNext()
THEN this.currentInstance = this.enumerator.Current

ルール 3 から N (優先度 = 0)

.... //additional rules written against this.currentInstance

ルール N+1 (優先度 = -1)

// can be any condition as long as it is evaluated every time;
// this.currentInstance will be evaluated each time 
//this.currentInstance changes, whereas 
// "1==1" would only be evaluated once
IF this.currentInstance == this.currentInstance  
                                                                           
THEN ...
         Update("this/enumerator") //this will cause Rule 2 to be reevaluated
ELSE ...
          Update("this/enumerator")

追跡とトレース

追跡

RuleSet が実行されると、追跡イベントは 、追跡プロファイルに UserTrackPoint を追加することによって、これらのイベントに登録したホストで構成された追跡サービスに送信されます。 RuleActionTrackingEvent が送信されます。このイベントは、評価されたルールの名前と、条件の評価結果 (true/false) を提供します。 例については、SDK の RuleActionTrackingEvent サンプルを参照してください。

アクティビティに対するルール条件の評価結果は、アクティビティの実行を追跡することで暗黙に追跡できます。

トレース

追加の RuleSet 評価情報をログ ファイルに送信するには、アプリケーション構成ファイルに次を追加します。

<configuration>
   <system.diagnostics>
      <switches>
           <add name="Rules" value="Information"/>
      </switches>
   </system.diagnostics>
</configuration>

次の情報がログ ファイルに送信されます。

  • 条件の依存関係情報:
    • 例: ルール "ReturnNumberOfStops" 条件の依存関係: "this/currentFlight/OutboundFlight/NumberOfStops/"
  • アクションの副作用情報:
    • 例: ルール "ReturnNumberOfStops" THEN 副作用: "this/currentFlight/Score/"
  • チェーン関係:
    • 例: ルール "ReturnNumberOfStops" THEN actions trigger rule "ApprovedFlights"
  • RuleSet の実行:
    • 例: ルール: "RuleSet FlightRuleSet の実行"
  • 条件の評価:
    • 例: ルール: ルール "SetDefaultScore" に対する条件の評価
  • 条件評価の結果:
    • 例: ルール: 条件が True に評価されました
  • アクションの実行:
    • 例: ルール: ルール "SetDefaultScore" の評価 THEN アクション

現在、すべてのトレース メッセージは "情報" レベルで定義されているため、ルールのトレースを表示するには、構成ファイルで Information または Verbose のレベルを指定する必要があります。

まとめ

WF には、さまざまな方法で利用できる柔軟なルール機能が用意されており、さまざまなシナリオをサポートできます。 シンプルなアクティビティ条件から高度な前方チェーン RuleSets まで、このテクノロジを使用すると、ルールのサポートをワークフローにシームレスに統合できます。 さらに、ルール エンジンをワークフローの外部で利用して、任意の .NET アプリケーションにルール機能を提供することもできます。

この機能セットを使用すると、新しい開発者はワークフローに簡単なルールを簡単に組み込むことができますが、さらに高度な RuleSet とアプリケーション シナリオをサポートするための豊富さと拡張性が提供されます。 このドキュメントは、次のセクションで引用したリソースと組み合わせることで、WF ルールを初めて使用する開発者がテクノロジについて学習し、その使用によって迅速に生産性を高めるのに役立ちます。

詳細情報

  • MSDN ワークフロー サイト

    Web キャストとラボへの多数のドキュメントとリンク。

  • コミュニティ サイトのサンプル

    • External RuleSet Toolkit — ワークフロー アセンブリからルールを外部化する方法の例を示します。
    • RuleSet 分析 - ルール間のリレーションシップとルールとデータの間のリレーションシップについて RuleSet を分析するツールです。
    • Excel のルール — ワークフローの外部でスタンドアロンのルールを使用する方法の例を示します。 また、Excel のデシジョン テーブルを使用して作成されたルールをプログラムで作成する方法も示します。
  • SDK のサンプル

    • IfElseWithRules — IfElse アクティビティに対する RuleCondition の使用を示します (\Technologies\RulesAndConditions の下)。
    • DynamicUpdateChangingRules — 動的更新 API を使用して、実行中のワークフロー インスタンス (\Technologies\RulesAndConditions) で RuleCondition を変更する方法を示します。
    • SimplePolicy — API を使用して、単純な RuleSet とポリシー アクティビティ (\Technologies\Activities\Policy) を定義する方法を示します。
    • AdvancedPolicy — より複雑な RuleSet (\Technologies\Activities\Policy) を定義します。
    • RuleActionTrackingEventSample - 追跡プロバイダー (\Technologies\Tracking) でルール評価結果をキャプチャする方法を示します。
  • MSDN ワークフロー フォーラム

    • WF ルールまたは WF 全般に関する質問については、こちらのディスカッション フォーラムを参照してください。

 

筆者について

Jurgen Willis は、Windows Workflow Foundation チームのプログラム マネージャーであり、ルール エンジンテクノロジとルール駆動型アクティビティを担当しています。 Microsoft に入社する前は、Jurgen は Fortune 500 企業向けの統合およびプロセス管理ソリューションを設計および実装しました。