松崎 剛 Blog

This Blog's theme : エンタープライズ開発 (Server side)、Office サーバ開発

[T2-401 デモ (3)] WF による Rule Base のアプリケーション

[T2-401 デモ (3)] WF による Rule Base のアプリケーション

  • Comments 3

こんにちは。

  1. WCF の Transport レベルの Custom Channel Sample
  2. Rehosting を使ったエンドユーザへのワークフロー公開
  3. WF による Rule Base のアプリケーション
  4. Custom の SharePoint Workflow Editor

製品開発者向けということで実施した Tech Ed の T2-401 セッションですが、お約束通り、デモを添付しておきます。

つぎは、WF の説明で 2 番目にご紹介した、ルールベースアプリケーションのサンプルです。

download sample

WF で、コード条件と、宣言型の条件に分かれている理由についてはセッションでご説明した通りです。このサンプルは、その後者のメカニズムを使用した製品サンプルでした。 

コードは以下の通りです。

WF の Rule は、CodeDom を使って編集することができました。ここでも、前回のサンプルで登場した WorkflowMarkupSerializer を使って .rules ファイルへの変換と読み込みが可能です。
このサンプルでは、Excel 上の各行 (4 行目 - 8 行目) に設定された内容を元にこの宣言型のルールを作成しています。(CodeDom の構成について忘れた方は、セッションの資料を見直してください)

private void button1_Click(object sender, EventArgs e)

{

    Excel.Range cell;

 

    RuleSet myRuleset = new RuleSet("RuleSet1");

 

    // Define property and activity reference expressions through CodeDom functionality

    CodeThisReferenceExpression refexp = new CodeThisReferenceExpression();

    CodePropertyReferenceExpression refTotalCost = new CodePropertyReferenceExpression(refexp, "totalCost");

    CodePropertyReferenceExpression refParamCategory = new CodePropertyReferenceExpression(refexp, "paramCategory");

    CodePropertyReferenceExpression refParamPrivilege = new CodePropertyReferenceExpression(refexp, "paramPrivilege");

 

    // Example :

    // IF paramCategory == 3

    // THEN totalCost = totalCost + 300

 

    for (int row = 4; row <= 8; row++)

    {

        cell = (Excel.Range)this.Cells[row, 2];

        if (String.IsNullOrEmpty((string)cell.Value2))

            break;

        Rule myRule = new Rule("Rule" + row);

        myRuleset.Rules.Add(myRule);

 

        // Example :

        // paramCategory == 3

        CodeBinaryOperatorExpression ruleCondition = new CodeBinaryOperatorExpression();

        if ((string)cell.Value2 == "種別 (category)")

            ruleCondition.Left = refParamCategory;

        else if ((string)cell.Value2 == "特典 (privilige)")

            ruleCondition.Left = refParamPrivilege;

        ruleCondition.Operator = CodeBinaryOperatorType.ValueEquality;

        cell = (Excel.Range)this.Cells[row, 3];

        ruleCondition.Right = new CodePrimitiveExpression((int)(double)cell.Value2);

        myRule.Condition = new RuleExpressionCondition(ruleCondition);

 

        // Example :

        // totalCost = totalCost + 300

        CodeAssignStatement ruleAction = new CodeAssignStatement();

        ruleAction.Left = refTotalCost;

        CodeBinaryOperatorExpression actionRight = new CodeBinaryOperatorExpression();

        actionRight.Left = refTotalCost;

        cell = (Excel.Range)this.Cells[row, 4];

        if((string)cell.Value2 == "+")

            actionRight.Operator = CodeBinaryOperatorType.Add;

        else if ((string)cell.Value2 == "-")

            actionRight.Operator = CodeBinaryOperatorType.Subtract;

        else if ((string)cell.Value2 == "*")

            actionRight.Operator = CodeBinaryOperatorType.Multiply;

        else if ((string)cell.Value2 == "/")

            actionRight.Operator = CodeBinaryOperatorType.Divide;

        cell = (Excel.Range)this.Cells[row, 5];

        actionRight.Right = new CodePrimitiveExpression((int)(double)cell.Value2);

        ruleAction.Right = actionRight;

        myRule.ThenActions.Add(new RuleStatementAction(ruleAction));

    }

 

    // 必要に応じ、RuleValidation オブジェクトを使ってチェック!

    // (今回は省略 . . . . . . .)

 

    // RuleDefinitions を設定して保存

    RuleDefinitions ruleDef = new RuleDefinitions();

    ruleDef.RuleSets.Add(myRuleset);

    WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();

    cell = (Excel.Range) this.Cells[11, 2];

    XmlTextWriter writer = new XmlTextWriter((string) cell.Value2, System.Text.Encoding.Unicode);

    serializer.Serialize(writer, ruleDef);

    writer.Close();

 

    // ここでは、すぐにコンパイルして実行

    // (Custom WorkflowRuntime Service Custom Policy Activity を作成して、データベースなど独自の Rule Cache を作成することなども可能です . . .)

 

    MessageBox.Show("ルールを反映しました");

} 

反映されたルールは、xoml (アプリケーションマークアップファイル) とは異なり実行時に読み込まれました。しかし、標準の PolicyActivity, ConditionedActivityGroup, While 等はアセンブリに埋め込まれたルールファイルを見にいくという意地悪な構成になっていたので、これを改造する必要がありました。このルールメカニズムで活躍するのは RuleEngine オブジェクトです。
下記のコードは、外部ファイルやデータベースなどを見に行くようにするようカスタムのアクティビティを作成しています。(ここでは逆に、WorkflowMarkupSerializer で、宣言を読み込んでいます。)

protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)

{

    XmlReader reader = new XmlTextReader(RuleFilePath);

    WorkflowMarkupSerializer serializer = new WorkflowMarkupSerializer();

    RuleDefinitions ruleDef = (RuleDefinitions)serializer.Deserialize(reader);

    reader.Close();

 

    // ルートアクティビティを取得

    Activity root = this;

    while (root.Parent != null)

        root = root.Parent;

 

    for (int i = 0; i < ruleDef.RuleSets.Count; i++)

    {

        RuleSet myRuleSet = ruleDef.RuleSets[i];

        RuleEngine ruleEng = new RuleEngine(myRuleSet, root.GetType());

        ruleEng.Execute(root, executionContext);

    }

 

    return base.Execute(executionContext);

}

 

Page 1 of 1 (3 items)
Leave a Comment
  • Please add 6 and 8 and type the answer here:
  • Post