在上一篇文章《MOSS多级审批工作流【StateMachine版】》中,有这样一个情景,我创建了两个任务,并且要等到这两个任务都完成后,根据其结果进行一些操作。在这一部分,我遇到一个问题,如何并行的处理这两个任务呢?
已知一个EventDrivenActivity不能跳转到一个以上的StateActivity中,所以我只能在同一个StateActivity中处理这两个任务。于是又引出一个问题,既然要并行的处理这两个任务,那么就得将OnTaskChangedActivity分别添加到不同的EventDrivenActivity中,那么如何在两个任务都被修改之后再进行操作呢?也就是说,如何在两个EventDrivenActivity都结束之后继续操作呢?
在上一篇文章中,我的方法是每一次修改任务之后,都维护一个bool值,然后在每个EventDrivenActivity的最后添加IfElseActivity来判断两个bool值是否都为TRUE,如果都为TRUE,再根据任务审批结果跳转到不同的StateActivity。
这种方法固然没有问题,但终究有些繁琐,而且,如果我们修改了流程,需要使IfElseActivity中某一分支跳转到新添加的StateActivity,那么就得到逐个EventDrivenActivity内部修改。
其实我们完全可以把这种方法再抽象一下,为什么说状态机工作流是“事件驱动”工作流呢?是因为每一个状态都依靠事件来决定下一步的流转方向。
就拿在SharePoint工作流中为用户创建任务为例,我们在StateInitializationActivity中添加CreateTaskActivity来创建任务,然后在EventDrivenActivity中添加OnTaskChangedActivity来接收任务被修改的事件,根据任务修改的结果来决定跳转到哪个StateActivity。
那么CreateTaskActivity和OnTaskChangedActivity又是什么原理呢?CreateTaskActivity其实是从CallExternalMethodActivity继承而来,而OnTaskChangedActivity是从HandleExternalEventActivity继承而来,这两个活动一个用来调用宿主的方法,一个用来接收宿主的数据(如果想了解这两个活动,请参见我翻译的《WF编程 - 本地通信事件》(1、2))。
CreateTaskActivity调用SharePoint Service提供的的CrateTask方法来创建一个任务,当用户修改了任务时,SharePoint Service就触发OnTaskChanged事件,工作流中的OnTaskChangedActivity捕获了此事件,进行处理,使得工作流可以继续进行。
再回来思考我们的需求,不就是希望在每一次任务修改之后都能触发一个共同的事件,在利用此事件判断是否所有任务都已经完成吗?
那么参照CreateTaskActivity和OnTaskChangedActivity的方式,我们只需要这样做就可以满足要求了,在每一次任务被修改后,使用CallExternalMethodActivity调用一个方法,这个方法当然不可能是SharePoint提供的了,这需要我们自己提供,这个方法只做一件事情,就是触发一个事件。接着我们在同一个StateActivity中再添加一个新的EventDrivenActivity,在其内部添加一个HandleExternalEventActivity来接收这个事件,接着再利用IfElseActivity来判断所有任务的处理结果并执行相应的跳转。 这样做的好处是把以前每个EventDrivenActivity中的IfElseActivity独立成为一个单独的部分,利用WF的本地通信服务,我们仍然可以实现每一次修改活动,都执行IfElseActivity,但如果需要修改跳转的目标StateActivity,再也不需要逐个修改了。
但是在这个示例中,我并没有直接用CallExternalMethodActivity和HandleExternalEventActivity活动,而是继承它们来得到两个自定义活动,为什么要这样做呢?
前边提到,CallExternalMethodActivity会调用一个方法,这个方法需要我们自己提供,那么我们就要编写相应的接口和实现这个接口的服务,最重要的是,我们必须在ExternalDataExchangehangeService中添加这个服务,然而SharePoint Service并不允许我们接触Workflow Runtime,好在如果开发自定义活动的话,在活动的Execute方法中,我们可以通过ActivityExecutionContext的相关方法获得ExternalDataExchangehangeService,然后为其添加自定义服务。
关于WF本地通信服务的机制和开发方法,请参见我翻译的《WF编程 - 触发事件与调用方法》(1、2、3)。
这篇逻辑混乱的说明文到此结束,各位朋友倘若看的不明白,那一定是我的文笔太差,下载源码一看便能明白了。
点击下载源码(本例为MOSS多级审批工作流【StateMachine版】的修改版)
注:
- 请用Visual Studio 2008打开源码
- 需要SharePoint Service支持
- 编译之后请手工将WindStyle.WindowsWorkflow.Activities.dll添加到GAC