小心调用Replicator, While 和 CAG子活动
前一阵子基于WWF开发时,在WhileActivity中放置了一个自定义的审核活动A1,基于审核结果A1.Approved作为执行条件。但是每次A1.Approved的值都是false。我在程序中设置断点,在执行期间查看了A1的Approved为True,但是第二次执行时又为false了。
这就是我们在这类具有回转功能的复合活动时需要注意的问题,否则很可能你的代码不跟着你的感觉走了,下面我讲一些出现这种情况的原因,以及如何开发这类应用。
使用工具Reflector查看System.Workflow.Activities的WhileActivity代码。
//活动执行时执行的代码,ActivityExecutionContext 为活动执行的上下文信息
protected override ActivityExecutionContext Execute(ActivityExecutionContext executionContext)
{
if (executionContext == null)
{
throw new ArgumentNullException("executionContext"); }
//开始执行本活动,内部生成一个新的上下文执行环境
if (this.TryNextIteration(executionContext))
{
return ActivityExecutionStatus.Executing;
}
return ActivityExecutionStatus.Closed;
}
private bool TryNextIteration(ActivityExecutionContext context) { ... if (base.EnabledActivities.Count > 0) { //内部生成一个执行上下文,子活动上下文中基于WhileActivity中放置的活动来生成子活动 ActivityExecutionContext context1 = context.ExecutionContextManager.CreateExecutionContext(base.EnabledActivities[0]); context1.Activity.RegisterForStatusChange(Activity.ClosedEvent, this); context1.ExecuteActivity(context1.Activity); } return true; } 在WWF中有个重要的概念:在具有多次执行子活动的复合活动内部执行时生成克隆的执行上下文 |
在WWF中提供了 Replicator, While 和 CAG可以多次执行子活动。WF内部给每次执行重新生成一个ActivityExecutionContext ,这样就比较容易处理补偿操作吧。
ActivityExecutionContext作为Execute, Cancel, HandleFault等参数,也通过sender (QueueItemAvailable handler, StatusChanged handler)传递。 ActivityExecutionContext提供控制Activity的接口。
internal ActivityExecutionContext(Activity activity) { this.currentActivity = activity; } |
每个context都有一个root activity,而且只有在context中的activities才能在当前上下文执行。
当子活动需要多次执行时,ActivityExecutionContext childContext = currentContext.ExecutionContextManager.CreateExecutionContext(reviewActivity);
执行代码将生成一个新的上下文,树型结构表示成:
RootContext
| whileActivity (1)
| reviewActivity (1)
- childContext(reviewer=张三)
| reviewActivity (2)
- childContext(reviewer=李四)
| reviewActivity (3)
whileActivity (1)和reviewActivity (1)是我们在workflow的Activities中添加的
活动,reviewActivity (2)和reviewActivity (3)是基于reviewActivity (1)模板生成活动。由于审核活动加入工作流时默认Approved为false,所以不管这个活动在while中执行多少次或者审核结果是否通过,每次执行时获取当前上下文的审核活动的Approved都是false。可以把reviewActivity (2)和reviewActivity (3)想象成reviewActivity (1)的实例。
我们可以通过在工作流中设置一个变量来解决传递审核结果的问题。
在上面这个例子中,reviewActivity (2)和reviewActivity (3)实例之间互不影响,whileActivity.Activities[0]将总是 reviewActivity (1),reviewActivity (3)
.Parent.Activities[0]也是reviewActivity (1)
链接有一部分讲了本文的内容