随笔 - 234, 文章 - 12, 评论 - 1671, 阅读 - 74万
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

动态更新活动条件

Posted on   生鱼片  阅读(1846)  评论(1编辑  收藏  举报

活动的条件有两种:代码条件和声明性规则条件。如果我们改变了代码条件我们需要重新编译我们的工作流程序才可以。由于声明行规则条件是序列化到.rules文件中的,所以我们可以动态的更新,下面举例说明:

我们建立一个顺序型工作流控制台程序,工作流设计如下图:

Condition1

然后分别设置分支条件(均为声明性规则条件)如下:
ifElseBranchActivity1:条件名--ifBranch1,表达式--this.conditonNum == 1。
ifElseBranchActivity2:条件名--ifBranch2,表达式--this.conditonNum == 2。

工作流代码如下:

using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;

namespace CaryUpdateCondition
{
    public sealed partial class ConditonWorkflow: SequentialWorkflowActivity
    {
        public ConditonWorkflow()
        {
            InitializeComponent();
        }
        public int conditonNum { get; set; }

        private void codeActivity1_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("第一个分支执行了");
        }
        private void codeActivity2_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("第二个分支执行了");
        }
        private void codeActivity3_ExecuteCode(object sender, EventArgs e)
        {
            Console.WriteLine("第三个分支执行了");            
        }
    }
}
我们设计宿主程序如下:
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(); }; workflowRuntime.WorkflowCreated += new EventHandler<WorkflowEventArgs>
(workflowRuntime_WorkflowCreated); Console.WriteLine("--第一个工作流执行开始--"); Dictionary<String, Object> argNum= new Dictionary<string, object>(); argNum.Add("conditonNum", 1); WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof
(CaryUpdateCondition.ConditonWorkflow),argNum); instance.Start(); waitHandle.WaitOne(); Console.WriteLine("--第一个工作流执行结束--"); Console.WriteLine(); Console.WriteLine("--第二个工作流执行开始--"); Dictionary<String, Object> argNum2 = new Dictionary<string, object>(); argNum2.Add("conditonNum", 2); WorkflowInstance instance2 = workflowRuntime.CreateWorkflow(typeof
(CaryUpdateCondition.ConditonWorkflow), argNum2); instance2.Start(); waitHandle.WaitOne(); Console.WriteLine("--第二个工作流执行结束--"); } }

如果这个时候我们执行工作流,和我们以前的没什么区别,程序会执行codeActivity1和codeActivity2,我们现在要在运行时动态更改活动的条件,什么时候做更新我们在WF中的动态更新 一文有详细的说明。我们注册WorkflowRuntime的Created事件。在该事件中做更改。代码如下:

private static Boolean firstWF = true;
private static void ModifyRules(WorkflowEventArgs e) { WorkflowChanges wc = new WorkflowChanges(e.WorkflowInstance.GetWorkflowDefinition()); RuleDefinitions rds = (RuleDefinitions)wc.TransientWorkflow.GetValue
(RuleDefinitions.RuleDefinitionsProperty); if (rds != null) { if (rds.Conditions.Contains("ifBranch1")) { RuleExpressionCondition condition= rds.Conditions["ifBranch1"]
as RuleExpressionCondition; CodeBinaryOperatorExpression codeExpression =condition.Expression
as CodeBinaryOperatorExpression; codeExpression.Right = new CodePrimitiveExpression(0); ValidationErrorCollection errors = wc.Validate(); if (errors.Count == 0) { try {e.WorkflowInstance.ApplyWorkflowChanges(wc);} catch (Exception ex) { Console.WriteLine("动态更新异常: {0}",ex.Message); } } else { foreach (ValidationError error in errors) { Console.WriteLine(error.ToString()); } } } } firstWF = false; }
现在我们再次运行程序,由于我们在上面的程序中将ifElseBranchActivity1的条件this.conditonNum == 1。右面
的表达式改为了0,结果如下:
Condition2 
我们在上面的程序中在运行时对ifElseBranchActivity1的条件做了更改,从结果中也看到更改生效,我们还可以在
运行时替换整个.rules文件,这样我们就可以在外部集中管理工作流的规则条件,我们现在将原来的自动生成的.rules
文件拷贝一份,重名为ReplaceRules.rules,然后把该文件中以下部分做更改,同样是将ifElseBranchActivity1
的条件this.conditonNum == 1,右面的表达式改为了0:
<ns0:CodeBinaryOperatorExpression.Right>
 <ns0:CodePrimitiveExpression>
   <ns0:CodePrimitiveExpression.Value>
    <ns1:Int32 xmlns:ns1="clr-namespace:System;Assembly=mscorlib, Version=2.0.0.0, 
Culture=neutral, PublicKeyToken=b77a5c561934e089
">0</ns1:Int32> </ns0:CodePrimitiveExpression.Value> </ns0:CodePrimitiveExpression> </ns0:CodeBinaryOperatorExpression.Right>


实际中我们不会这样做,我们会通过规则编辑器来设置我们的规则,我们在运行时替换该规则文件,程序如下:
private static void ReplaceRules(WorkflowEventArgs e)
{             
    WorkflowChanges wc = new WorkflowChanges(e.WorkflowInstance.GetWorkflowDefinition());                        
    Stream stream = new FileStream(@"ReplaceRules.rules", FileMode.Open, 
FileAccess.Read, FileShare.Read); using (XmlReader xmlReader = XmlReader.Create( new StreamReader(stream))) { WorkflowMarkupSerializer markupSerializer= new WorkflowMarkupSerializer(); RuleDefinitions ruleDefinitions= markupSerializer.Deserialize(xmlReader)
as RuleDefinitions; if (ruleDefinitions != null) { wc.TransientWorkflow.SetValue(RuleDefinitions.RuleDefinitionsProperty,ruleDefinitions); ValidationErrorCollection errors = wc.Validate(); if (errors.Count == 0) { try { e.WorkflowInstance.ApplyWorkflowChanges(wc);} catch (Exception ex) { Console.WriteLine("动态更新异常: {0}",ex.Message); } } else { foreach (ValidationError error in errors) { Console.WriteLine(error.ToString()); } } } } firstWF = false; }

运行程序后我们会得到和上面同样的结果。

编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· .NET周刊【3月第1期 2025-03-02】
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
点击右上角即可分享
微信分享提示