关于动态更新
在开发工作流时,我们会在工作流设计器中通过拖拽活动,设置属性等等来设计我们的工作流,我们 希望我们在设计时定义好的工作流在运行时是不变的。但在实际中我们往往需要在运行时来改变工作流 的架构,例如我们已经定义好的流程在没有结束时我们需要增加一个流程点,这个时候我们就需要使用 动态更新来现实。在WF中我们也可以对正在运行的工作流实例添加删除活动,修改活动,规则条件等。 当动态更新应用到工作流实例上时,只影响当前的工作流实例。其他的和将来的都不受影响,仍然使用 原始的工作流定义。
动态更新不适合要进行整体更改的情况,因为这将导致工作流与原始设计原则产生极大差别。 在此 类情况下,应设计一个新的工作流,而不是对正在运行的实例进行更改。动态更新不必重新编译和重新 启动工作流。
何时进行动态更新
我们可以从工作流的执行线程内部和外部对正在运行的工作流实例进行动态更新。 在内部,我们可 以使用CodeActivity,自定义活动等来实现,由于工作流运行在单一的线程上,所以我们执行动态更新 的时候不会有其他的活动在执行。 在外部,我们实现动态更新就有严格规定,主要有以下状态可以在宿 主程序中进行动态更新:
1. 工作流实例创建完成,但是没有开始。
2. 工作流实例是挂起状态,没有恢复。
3. 工作流实例是空闲状态。
我们可以在WorkflowRuntime的WorkflowCreated,WorkflowSuspened,WorkflowIdled事件中来完成 动作更新。WorkflowCreated事件在workflowRuntime.CreateWorkflow方法调用后引发,使用使用 SuspendActivity可以使工作流转到挂起状态,引发WorkflowSuspened事件。使用DelayActivity或 HandleExternalEventActivity时工作流会进入Idle状态,引发WorkflowIdled事件。
动态更新的一般步骤
我们通过以下几个步骤进行动态更新:
1.所有对运行中工作流实 例的建议的更改必须使用WorkflowChanges对象进行。首先我们要创建一个该类的实例,构造函数中需要 需要传递被更改的工作流实例的根活动。如果你是使用内部实现动态更新的方式,你直接传递this关键 字就可以了。如果你是在外部宿主程序中,你需要使用workflowinstance的GetWorkflowDefinition方法 来获取工作流实例的根活动。
2.WorkflowChanges对象被创建后。该对象的TransientWorkflow属 性返回该工作流实例的克隆版本,我们会对该克隆版本进行更改,然后将更改应用到运行中的工作流实 例。
3.我们需要找到你要添加或删除活动的父活动,可以使用CompositeActivity的Activities 属性或是使用GetActivityByName方法来确定父活动,然后使用Add或Insert方法来添加或插入新的活动 。移除活动使用remove方法。
4.使用WorkflowChanges的Validate方法来验证,如果有错误会返 回ValidationError对象集合。
5.验证通过后就可以更新了,如果是在外部实现动作更新需要调 用workflowinstance对象的ApplyWrokflowChange方法,内部的话就调用当前对象的 ApplyworkflowChanges方法。
阻止动态更新
顺序和状态机工作流都有一个 DynamicUpdateCondition属性,如果你没有设置该属性工作流一直允许动态更新,当你设置了该属性后 ,当你在调用ApplyWorkflowChanges方法时就会去计算,如果为true则允许进行动态更新,否则就会抛 出异常。
动态更新实例
下面我们分别使用在工作流内部和外部两种方式来举例说明,首 先我们建立一个顺序型工作流控制台程序,工作流设计如下图:
工作流代码如下:
public sealed partial class CaryDynamicUpdateWorkflow: SequentialWorkflowActivity
{
public CaryDynamicUpdateWorkflow()
{
InitializeComponent();
}
private void beforeSequence_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("beforeSequence执行了");
}
private void afterSequence_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("afterSequence执行了");
}
private void IsUpdate(object sender, ConditionalEventArgs e)
{
e.Result = true;
}
}
我们会在运行时给该工作流中的sequenceActivityContainer添加 一个自定义活动PrintActivity,该自定义活动仅仅向控制台输出一条语句,代码如下:
public partial class PrintActivity : System.Workflow.ComponentModel.Activity
{
public PrintActivity()
{
InitializeComponent();
}
protected override ActivityExecutionStatus Execute (ActivityExecutionContext executionContext)
{
Console.WriteLine("自定义 Print活动");
return base.Execute(executionContext);
}
}