環境 :
Visual Studio 2008 (.NET Framework 3.5)
こんにちは。
- WCF の Transport レベルの Custom Channel Sample
- Rehosting を使ったエンドユーザへのワークフロー公開
- WF による Rule Base のアプリケーション
- Custom の SharePoint Workflow Editor
製品開発者向けということで実施した Tech Ed の T2-401 セッションですが、お約束通り、デモを添付しておきます。
つぎは、WF の説明で 2 番目にご紹介した、ルールベースアプリケーションのサンプルです。
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 functionalityCodeThisReferenceExpression refexp = new CodeThisReferenceExpression();CodePropertyReferenceExpression refTotalCost = newCodePropertyReferenceExpression(refexp, "totalCost");CodePropertyReferenceExpression refParamCategory = newCodePropertyReferenceExpression(refexp, "paramCategory");CodePropertyReferenceExpression refParamPrivilege = newCodePropertyReferenceExpression(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 == 3CodeBinaryOperatorExpression 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 + 300CodeAssignStatement 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(ActivityExecutionContextexecutionContext){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);}
Categories: Uncategorized
PingBack from http://housesfunnywallpaper.cn/?p=3428
LikeLike
こんにちは。 WCF の Transport レベルの Custom Channel Sample Rehosting を使ったエンドユーザへのワークフロー公開 WF による Rule Base のアプリケーション
LikeLike
こんにちは。 WCF の Transport レベルの Custom Channel Sample Rehosting を使ったエンドユーザへのワークフロー公開 WF による Rule Base のアプリケーション
LikeLike