Windows 工作流活动技术概览
作为即将推出的 Microsoft .NET Framework 3.0 的重要组成部分,Windows Workflow Foundation 提供了编程模型和运行时引擎,以便基于安装了 .NET Framework 2.0 或更高版本的 Window 平台来构建支持工作流的应用程序,其最低运行要求为 Windows XP Service Pack 2 (SP2) 或 Windows Server 2003。
从软件的角度看,需要人为操作的多数是异步事件处理、状态保持以及共享服务器可用性。Windows Workflow Foundation 实际上支持任何涉及人为操作的情况。
每一个工作流都是一个声明程序,其中,每条程序语句都用称为活动的组件表示。关于 Windows Workflow Foundation 的最大误区之一在于将所有要素活动都看成是顺序相连或按状态机转换相连。实际上,Windows Workflow Foundation 对执行模型进行了活动自动控制方面的虚拟化。这使您能编写可以捕捉各种控制流模式的复合活动,范围包括多种连接和合并、状态机、图形、序列、交叉存取和非本地退出等。总之,它将使您能够通过“高保真”的复合活动对存在于现实世界中的控制流模式进行建模。然而,Windows Workflow Foundation 提供了针对以下两种模式的内置活动:顺序工作流和状态机工作流。
顺序工作流有明确的开始和结束点,从始至终,一步接一步,沿着一条可能的线路执行。状态机工作流可以被表示为一组状态,每种状态可能包括各种活动,并由事件触发。您可以定义初始和完成状态,并按照所有定义的转换过程逐个状态地执行,直至到达结束状态。
正如我所谈到的,工作流的构造块就是活动。构造这样一个工作流意味着将活动进行组合以创建所需的模型来解决遇到的问题。虽然 Windows Workflow Foundation 提供了很多内置的活动,但依然可以通过自定义活动对其进行完全扩展。了解“开箱即用”活动的目标和功能对于充分理解该平台的真实潜能十分关键。本期专栏将带您浏览安装 Windows Workflow Foundation Runtime 和 Visual Studio 2005 Designer 时涉及的标准工作流活动。
“开箱即用”活动
Windows Workflow Foundation 是 .NET Framework 3.0 (原先称为 WinFX?)的组成部分。虽然它只是一个测试版本,但我发现最新的 Community Technology Preview(社区技术预览,CTP)版非常稳定,许多公司正广泛使用该版本开发应用程序。因此,已经出现大量工具和自定义活动,一个基于新闻组和论坛(如 wf.netfx3.com)的有效的技术支持社区正日益发展壮大。如果您对工作流应用程序感兴趣,那么越早熟悉它越好。
若要查找最新的下载,请访问 Windows Workflow Foundation。安装完毕后,启动 Visual Studio 2005,打开一个 Visual Basic? 或 C# 工作流项目,查看工具箱中的内容。根据您所选择的项目类型,工具箱可能如图 1 中所示的一种。
工具箱中的内容与您的选择操作相关,根据您所选择的工作流的类型会有不同。特别是,图 1 左边的工具箱还包含您创建状态机工作流时所需的状态活动。右边的工作箱窗口只包含顺序工作流的活动。这组预定义的活动可根据目标和预期的行为分为几类。图 2 显示了可能的分类:控制流、执行、事件、Web 服务和状态机。
![]() 图1 工具箱里的工作流活动(Click the image for a smaller view) ![]() 图2 |
控制流活动管理图形活动执行的顺序。列表列出了实现循环的条件块以及构造。执行活动包括多种构造,这些构造可终止或挂起工作流、引发异常、执行内部或外部代码,或者生成另一个工作流。多数工作流需要与主机环境同步 — 通常是 Windows Forms 应用程序或 ASP.NET 应用程序。事件组中的活动能使工作流停止以等待外部事件、处理接收的事件,或只是在执行下一步之前进行等待。最后,Web 服务和状态组将目标锁定在工作流的两种特殊功能 — 将内部引擎为公开为 Web 服务或公开为状态机。让我们检查一下框架中的主要活动,然后分组进行。
通过条件控制工作流
如果在工作流中指定了条件,运行时引擎将对条件进行计算,然后根据计算结果进行操作。两种基于条件的核心活动是 IfElse 和 Policy。IfElse 活动的执行方式如同高级编程语言中的一条典型的 If 语句。它可以包含任意多基于条件的分支,以及一个在其他条件不满足情况下执行的默认分支。而 Policy 活动表示一系列规则。在 Windows Workflow Foundation 中,一条规则包括一个条件以及一个或一个以上引发的操作。可以将规则看作 If-Then-Else 语句,其中条件对应 If 块的 Boolean 临界条件,操作定义了 Then 和 Else 子句。让我们进一步了解各个活动,然后对它们进行比较。
当被添加到一个工作流中时,IfElse 活动看起如图 3 所示。默认情况下,它有两个分支,可以通过右键单击并从上下文菜单中进行选择来添加新的分支。当运行时引擎达到一个 IfElse 活动,它开始计算从左至右进行的各分支的条件。各分支的条件被确定,第一个计算结果为“true”的分支被运行。您可以通过活动的上下文菜单中的命令来回移动分支以更改分支的计算顺序。要启用分支,需要指定有效的条件。您可以采用以下两种方法中的一种来指定条件:通过表达式或通过一段代码。
![]() 图 3 IfElse 的实际活动(Click the image for a larger view) |
如果您选择使用表达式来指定条件,则要在设计器设置分支,并为 Visual Studio 2005 的“属性”框中的“条件”项提供一个公共存放位置。接下来,打开表达式编辑器,输入一个涉及工作流成员并且其计算值为布尔值的表达式。例如,如果工作流类具有名为 MinimumLength 的公共属性,您可以将条件设置如下:
| this.MinimumLength >= 8 |
图 4 所示的编辑器完全支持 IntelliSense? 并提供对工作流私有成员和公共成员的访问。这意味着您也可以调用 Boolean 函数。假设您有一个属性声明如下:
| Public Property MinimumLength() As Integer Get Return _minLength End Get Set(ByVal value As Integer) _minLength = value End Set End Property |
![]() 图 4 针对 IfElse 活动的 Condition Editor(Click the image for a larger view) |
当您试图读取 MinimumLength 的值时,运行时会结束调用属性的 get 存取器。该存取器能够回复私有成员 _minLength 的值。IfElse 活动中的最后分支可以没有条件。在这种情况下,它将作为 IF 工作流语句的 Else 分支。
指定条件的第二种方法是通过临时代码。在这种情况下,您可以为工作流类添加方法,例如:
| Sub EvalCondition(ByVal sender As Object, ByVal e As ConditionalEventArgs) e.Result = ... '' Boolean value End Sub |
该函数必须与接受对象和 ConditionalEventArgs 类并回复 void 的签名相匹配。ConditionalEventArgs 类的 Result 成员将设置为布尔值,代表条件的计算结果。
IfElse 活动可以进行嵌套以表示复杂的逻辑,但逻辑的设计仍然要在工作流中进行硬编码。这种方法既有利也有弊。有利的一面在于它使您可以根据您的需求准确设计工作流并将其与其他活动整合。当您需要创建一组规则来初始化部分工作流状态时,其不利的一面就显现出来。让一连串 IfElse 活动仅仅为工作流的内部成员分配值显然有些矫枉过正。
当您真正需要控制工作流的流动并连接各种工作块时,您应该使用 IfElse 活动组合。如果您所需要的仅仅是一个编程 If 语句序列,带有附加到分支的简单代码,那么最好使用 Policy 活动。Policy 活动是一个规则集合。与各规则相关的代码仅限于设置工作流属性,调用工作流方法或针对引用的程序集中的类型的静态方法。
活动与已排序的规则集合相关联,您可以通过编辑器定义规则。每条规则都有优先级和 Active 属性。这两种属性的组合确定了是否应当评估规则,以及采用哪种优先级。另外,规则还必须指定重估行为 —“Always(始终)”(默认值)或“Never(从不)”。如果设置为“Always”,规则将根据需要进行重估,否则只进行首次评估,以后无论工作流状态如何变化,也不再更改。
