• 如何开发一个基本的复合活动


    WF提供的标准活动中有很多复合活动,这些复合活动可以添加子活动比如:SequenceActivity,ParallelActivity,ReplicatorActivity等。这些活动都有特定的用途,如果WF提供的标准活动都不满足我们的需要的时候,我们就要自己开发一个复合活动。

    活动的状态模型
    活动在他的生命周期中有六种状态。 这些状态分别为 Initialized、Executing、Canceling、Closed、Compensating 和 Faulting。下图摘自MSDN中说明活动之间状态的转换关系:

    AC

    1.红色实线表示工作流运行时引擎负责将活动从 Initialized 状态转换到 Executing 状态,或从 Closed 状态转换到 Compensating 状态。
    2.黄色实线表示父活动负责将子活动从 Executing 状态转换到 Closed 状态。 如果您创建自定义复合活动,则必须亲自进行处理。
    3.蓝色实线表示工作流运行时引擎负责将活动从 Executing、Canceling 或 Compensating 状态转换到 Faulting 状态。
    4.黄色虚线表示工作流运行时引擎负责将活动从 Canceling 状态、Compensating 状态或 Faulting 状态转换到 Closed 状态。
    5.仅当所有子活动都处于 Closed 或 Initialized 状态时,才能关闭活动。

    活动执行上下文(AEC)
    AEC是在宿主应用程序调用 Start 方法时为活动创建的执行环境。AEC可以使用ExecuteActivity 或CancelActivity方法来执行或取消 子活动。 也可以通过 CloseActivity方法 方法来关闭自己。 这些是仅有的父活动可以通过 AEC 控制的执行状态更改。 所有其他活动状态都是由工作流运行时引擎控制的。

    关于活动状态和AEC的在《WF本质论》的前几章中有非常详细的讲解,推荐大家去看看。

    开发一个自己的SequenceActivity
    WF中所有的复合活动都继承子CompositeActivity,要开发一个基本的复合活动一般有以下几个步骤:
    1.重写基类的Execute方法,在该方法中安排第一个子活动的执行,如果没有子活动要执行就返回Closed状态。还需要注册状态更改事件。
    2.处理状态更改事件,在此我们判断是否还有子活动要执行,如果有就继续执行,如果没有就调用AEC的CloseActivity来关闭活动。
    3.重写基类的Cancel方法,处理如当有异常发生的时候来执行的取消逻辑。

    下面我们就开发一个自己的SequenceActivity,我们建立一个顺序型工作流项目,新建一个自定义活动,代码如下:[Designer(typeof(SequentialActivityDesigner))]
    public partial classCarySequenceActivity: CompositeActivity,
                                IActivityEventListener<ActivityExecutionStatusChangedEventArgs>
    {...}
    该活动继承自CompositeActivity活动和接口IActivityEventListener<ActivityExecutionStatusChangedEventArgs>,IActivityEventListener接口用于监听活动的执行状态事件的更改的相关信息。

    1.我们首先重写基类的Execute方法,代码如下:
    protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext) { if (this.EnabledActivities.Count == 0) { return ActivityExecutionStatus.Closed; } else { this.EnabledActivities[0].RegisterForStatusChange(Activity.ClosedEvent, this); executionContext.ExecuteActivity(this.EnabledActivities[0]); } return ActivityExecutionStatus.Executing; }
    2.实现IActivityEventListener接口的OnEvent方法,代码如下:
    public void OnEvent(object sender,ActivityExecutionStatusChangedEventArgs e) { ActivityExecutionContext context = sender as ActivityExecutionContext; if (context == null) { throw new ArgumentException("Expected sender to be an ActivityExecutionContext","sender"); } e.Activity.UnregisterForStatusChange(Activity.ClosedEvent, this); Int32 activityIndex = this.EnabledActivities.IndexOf(e.Activity); if (activityIndex == this.EnabledActivities.Count - 1) { context.CloseActivity(); } else { activityIndex++; if (this.ExecutionStatus == ActivityExecutionStatus.Executing) { this.EnabledActivities[activityIndex].RegisterForStatusChange(Activity.ClosedEvent, this); context.ExecuteActivity(this.EnabledActivities[activityIndex]); } else if (this.ExecutionStatus == ActivityExecutionStatus.Canceling) { if (CancelProcessing(context)) { context.CloseActivity(); } } } }
    3.重写基类的Cancel方法,代码如下:
    protected override ActivityExecutionStatus Cancel(ActivityExecutionContext executionContext) { if (CancelProcessing(executionContext)) { return ActivityExecutionStatus.Closed; } else { return ActivityExecutionStatus.Canceling; } } private Boolean CancelProcessing(ActivityExecutionContext executionContext) { Boolean isTimeToClose = true; foreach (Activity activity in this.EnabledActivities) { if (!isTimeToClose) { break; } switch (activity.ExecutionStatus) { case ActivityExecutionStatus.Executing: executionContext.CancelActivity(activity); isTimeToClose = false; break; case ActivityExecutionStatus.Canceling: case ActivityExecutionStatus.Compensating: case ActivityExecutionStatus.Faulting: isTimeToClose = false; break; case ActivityExecutionStatus.Initialized: case ActivityExecutionStatus.Closed: break; default: break; } } return isTimeToClose;
    }
    4.这样我们就完成一个基本的复合活动,该活动的功能和WF提供的标准活动SequenceActivity相似,如果你现在使用
    Reflector反编译一下WF本身提供的SequenceActivity活动的源代码,你会发现我们的处理方式是几乎相同的。我们
    就来测试一下该活动,生成项目后,我们在工作流设计器上拖入CarySequenceActivity活动,向该活动内放几个
    CodeActivity活动,
    如下图:
    ComAc1 
    5.运行工作流,我们可以看出几个CodeActivity都正常执行了,如下图:
    ComAc2 
    你也可以测试当该活动的子活动正在执行的时候,工作流发生了异常,此时就会执行该活动的取消逻辑。在此我们就不再测试了。
     

    作者:生鱼片
             
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    MySQL 连接的使用:语法及案例剖析、INNER JOIN、LEFT JOIN、RIGHT JOIN
    MySQL GROUP BY 分组语句:语法及案例剖析、使用 WITH ROLLUP
    MySQL 排序:语法及案例剖析、在命令提示符中使用 ORDER BY 子句
    MySQL UNION 操作符:语法及案例剖析
    MySQL LIKE 子句:语法及案例剖析、在命令提示符中使用 LIKE 子句
    maven仓库
    maven安装配置
    Jedis
    Redis下载安装以及String类型
    Redis介绍
  • 原文地址:https://www.cnblogs.com/carysun/p/1319847.html
Copyright © 2020-2023  润新知