1.3      开发我们的第一个工作流

也许你曾经在这样的产品经理手下搞过开发:他总是在你身边转悠,并不时的问一句“你还没做完吗?”。在这一部分,我们将用一个简单的Windows Workflow程序把这个招人烦的产品经理替换掉。这个例程无法向你展示WF平台的全部功能,但它可以让你领略到如何用WF创建并运行工作流。

在开始之前,我们需要下载并安装.NET 3.0框架。安装程序可以在 http://netfx3.com 找到。Visual Studio 2005的所有版本都支持在.NET 3.0框架上的开发。我们还需要下载并安装Visual Studio 2005 Extensions for Windows Workflow Foundation。这个扩展包也可以在 http://netfx3.com 找到。但是这个扩展包不支持Visual Studio 2005 的Express版本。

首先,用Visual Studio新建一个Workflow工程(File | New Project)。我们选择使用C#开发,选择Sequential Workflow Console Application(顺序工作流控制台应用程序)模板(参见下面的截屏图)。模板为我们生成的工程包含有:对所有必要的WF程序集的引用,一个空工作流和一个用来驱动工作流的Program.cs文件。右键单击这个工作流,选择Delete(删除)操作,这样我们就能从零开始编制一个工作流了。

我们现在可以在Solution Explorer(解决方案管理器)窗口中右键单击工程文件,选择Add New Item(添加新项目)。在可添加项目列表中,我们选择Sequential Workflow(with code separation)(顺序工作流-代码分离),然后把这个新项目命名为workflow1.xoml(请见下面的截屏图)。这个XOML文件中就是用XAML标记码定义的我们的工作流。

如果展开Workflow1.xoml节点,我们就会看到包含一个分部类的代码旁置文件(Workflow1.xoml.cs)。前面说过,这个分部类将与XAML标记码定义的类共同生成一个完整类型。在下面的代码中,我们对Workflow1.xoml.cs中的类做了修改,添加了一个IsFixed属性及其支持字段。

public partial class Workflow1 : SequentialWorkflowActivity
{
private bool _isFixed; public bool IsFixed
{
get { return _isFixed; } set { _isFixed = value; }
}
}

如果双击.xoml文件,设计器窗口就会打开。此时如果Toolbox窗口还没有打开,我们可以用快捷键Ctrl+Alt+X打开它。我们可以从Toolbox中拖出一个While活动,并放置到工作流的起始点和终止点之间。While活动会重复执行其内部的子任务,直到某个条件得到满足为止。再拖出一个Code活动,把它放到While里面。现在,我们的设计器就是下面这个样子:

你看到了吗?每个活动都带着一个红叹号点。这就是说,两个活动的有效性验证都没通过。我们可以把鼠标停在叹号点上,点开智能标记后就能看到验证错误。如果现在就执行编译操作,验证错误就会作为编译错误出现在错误提示窗口中。让我们动手来修复这些错误。

Code活动要求我们为其ExecuteCode事件分配一个事件处理函数。我们可以在Code活动的Properties窗口中(用F4快捷键打开)完成这项分配操作。双击ExecuteCode属性旁边的空白处,相应的代码旁置文件就会打开,里面也已经有了一个自动生成的事件处理函数框架。我们把下面这段代码放到框架中。这段代码向用户询问软件缺陷是否已修复,然后等待用户按下一个键。如果用户按了“y”键,程序会将_isFixed字段设置为true。

private void codeActivity1_ExecuteCode(object sender, EventArgs e)
{
Console.WriteLine("Is the bug fixed?"); Char answer = Console.ReadKey().KeyChar; answer = Char.ToLower(answer); if (answer == 'y')
{
_isFixed = true;
}
else
{
Console.WriteLine();
Console.WriteLine("Get back to work!");
Console.WriteLine();
} }

Code活动的验证已经通过了,让我们来对付While活动。While活动需要一个有效的Condition(条件)属性。基本活动库中有好几个活动在执行时都需要“条件”,这其中就包括IfElse、ConditionedActivityGroup以及Replicator活动。第9章将会深入讨论条件与规则。

设置Condition属性的方法很简单:在Properties窗口中打开Condition属性旁边的下拉列表框,在CodeConditionRuleConditionReference中二选一。这两个供选项代表了两个不同的条件表述技术,前者用代码表述(一个返回布尔值的方法),后者用规则。这里选择RuleConditionReference一项。规则条件是一个命名表达式,它的评估结果是true或false,它能够存储在独立的.rules外部文件中,这样易于维护。现在,Condition属性旁边出现了一个加号,点击这个加号可以展开属性编辑器。

Condition属性被展开后,Properties窗口允许我们对ConditionName(条件名称)和Expression(表达式)进行设置。点击Condition旁边的省略号(…)按钮,Select Condition(选择条件)对话框就会弹出来。

点击New Condition…(新条件…)按钮会弹出下面的Rule Condition Editor(规则条件编辑器)。

我们打算让While活动循环执行直到缺陷被修复,因此我们输入的规则是 !this.IsFixed(编辑器自带的IntelliSense功能可以让我们偷点懒),然后点OK(确定)按钮。当返回到Select Condition对话框,可以看到编辑器已经把我们的条件命名为Condition1。请选择Condition1并点击OK。此时已经完成了对While活动ConditionNameExpression的设置,也通过了有效性验证。

现在打开Program.cs文件,这里的Main方法是控制台程序的入口点。我们需要承载WF运行时,并让它来执行我们的工作流。工作流工程模板中已经提供了所有我们需要的模板代码。请看下面的代码:

class Program
{
static void Main(string[] args)
{
WorkflowRuntime workflowRuntime = new WorkflowRuntime(); workflowRuntime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs> (workflowRuntime_WorkflowCompleted); workflowRuntime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs> (workflowRuntime_WorkflowTerminated); WorkflowInstance instance; instance = workflowRuntime.CreateWorkflow(typeof(Workflow1)); instance.Start(); waitHandle.WaitOne();
} static void workflowRuntime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message); waitHandle.Set();
} static void workflowRuntime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
waitHandle.Set();
} static AutoResetEvent waitHandle = new AutoResetEvent(false);
}

第一步是生成一个WorkflowRuntime实例。代码中已经为运行时指定了两个事件处理函数,因此如果工作流终止(因为异常)或结束了,我们都能够得到相应的通知。随后调用CreateWorkflow方法生成了一个缺陷修复工作流的实例,调用参数就是我们的工作流类型。因为工作流引擎是以异步方式执行工作流,我们就必须用一个AutoResetEvent对象将主线程阻塞,并等待工作流结束(不然的话,这个控制台程序可能会在工作流开始执行前就退出了)。AutoResetEvent对象会阻塞一个线程,直到该对象进入信号状态,而我们恰好是在前面提到的两个事件处理函数中调用AutoResetEvent对象的Set方法将其设为信号状态。

现在我们可以生成这个工作流解决方案,然后在命令行中运行它的可执行文件。

1.4      总结

软件开发者们从一开始就不断地使用工作流对业务流程进行建模与实现。在这期间,我们已经知道了工作流可能会长时间地运行,并经常需要得到用户的输入信息。通过创建一个健壮的工作流来应对这些挑战是一项令人望而生畏的任务。一种理想的工作流创建范例是将工作流的定义与工作流的执行引擎分离开。

一旦将工作流的定义与执行引擎分离,我们就可以通过构建工作流组件的方式编制出域特定语言。如果一个业务人员能够理解域特定语言,那么在忽略掉异常处理和状态追踪这些细节的情况下,他同样能够理解一个工作流。

Windows Workflow为微软平台带来了一个工作流执行引擎和一系列工作流开发工具。WF引擎的执行指令就是活动,我们可以利用图形化的设计器、XAML、代码或者它们三者的组合,对活动进行一番编排。WF还提供了一些工作流引擎所需的服务,这包括持久化服务、线程服务以及事务服务。因此我们可以说:用WF搞工作流开发,前途一片光明。

章节链接:

【翻译习作】 Windows Workflow Foundation程序开发

【翻译习作】 Windows Workflow Foundation程序开发-前言

【翻译习作】 Windows Workflow Foundation程序开发-第一章01

【翻译习作】 Windows Workflow Foundation程序开发-第一章02

【翻译习作】 Windows Workflow Foundation程序开发-第一章03

【翻译习作】 Windows Workflow Foundation程序开发-第一章04

【翻译习作】 Windows Workflow Foundation程序开发-第一章05的更多相关文章

  1. 【翻译习作】 Windows Workflow Foundation程序开发-第一章04

    1.2.3  Windows Workflow运行时 从Windows Workflow的角度看,可以将工作流活动当成是交给一个工作流处理器去执行的一系列指令或操作码.在Windows Workflo ...

  2. 【翻译习作】 Windows Workflow Foundation程序开发-第一章03

    1.2.2.Visual Studio 2005扩展包 微软也为Windows Workflow开发者提供了Visual Studio 2005扩展包.扩展包将许多功能集成到Visual Studio ...

  3. 【翻译习作】 Windows Workflow Foundation程序开发-第一章02

    1.2      Windows Workflow概览 微软的Windows Workflow Foundation(简称WF)是.NET框架3.0版的一部分..NET3.0其它主要部分是Window ...

  4. 【翻译习作】 Windows Workflow Foundation程序开发-第一章01

    第 1 章    欢迎来到工作流的世界 …思想如蝴蝶般飞到我身边 —— Gossard / Vedder (译注:Gossard与Vedder是来自Pearl Jam乐队的2名乐手,该句出自他们的歌曲 ...

  5. 【翻译习作】 Windows Workflow Foundation程序开发

    近期整理硬盘,把09年的翻译习作<Windows Workflow Foundation程序开发>找出来了.现在又把译文过了一遍,做了些修改,贴出来献丑了.原书是<Programmi ...

  6. 【翻译习作】 Windows Workflow Foundation程序开发-前言

    Windows Workflow Foundation程序开发-基于XAML和C#的WF实战技术与例程 ——C#程序员的WF功能与编程接口技术指导 前言 Windows Workflow Founda ...

  7. 你还记得windows workflow foundation吗

    很多年前,windows workflow foundation还叫WWF,而直译过来的名称让很多人以为它就是用来开发工作流或者干脆就是审批流的. 博主当年还是个懵懂的少年,却也知道微软不会大力推一个 ...

  8. Workflow-Microsoft:Windows Workflow Foundation

    ylbtech-Workflow-Microsoft:Windows Workflow Foundation 1. Windows Workflow Foundation返回顶部 1.1. Windo ...

  9. 微信小程序开发-第一弹

    前言:       本篇文章为大家详细介绍微信小程序开发第一篇,后续步骤会逐步更新,欢迎大家关注. 第一步  注册        1.1 打开网址 https://mp.weixin.qq.com/  ...

随机推荐

  1. pgsql 9.4修改数据库只读

    先进入psql 切换到目标数据库 \c mydb 对于老表 grant usage on schema public to $read_only_user; grant select on all t ...

  2. 什么是SQLCLR与使用

    原帖地址:http://www.cnblogs.com/hsrzyn/archive/2013/05/28/1976555.html 什么是SQLCLR SQL CLR (SQL Common Lan ...

  3. 【java】之转码

    GBK->UTF-8 String str = "任意字符串"; str = new String(str.getBytes("gbk"),"u ...

  4. MSSQL 随机查询且降序排列

    --随机查询且降序排列 * FROM dbo.COMPANY_USER_INFO ORDER BY NEWID()) AS T ORDER BY T.cu_id DESC

  5. html中select标签获取选中value和text

    $("#id").find("option:selected").text(); //获取Select选择的Text$("#id").val ...

  6. FindViewByMe插件

    FindViewByMe 是一个自动生成 FindViewById 代码的 IDEA/Android Studio 插件, 支持 Activity.Fragment 和 ViewHolder 中的 f ...

  7. HDU 2717 Catch That Cow(BFS)

    Catch That Cow Farmer John has been informed of the location of a fugitive cow and wants to catch he ...

  8. PHP解析JSON和XML方法

    一.JSON $r = json_decode("json数据"); $result = $r->result; //解析后的数据,以数组形式保存到r里面了,需要通过-> ...

  9. iPhone播放音乐

    来源:http://blog.csdn.net/htttw/article/details/7842295 iPhone播放音乐 今天我们简要介绍如何在iPhone中播放音乐: 强烈建议你参考官方文档 ...

  10. .nil? .empty? .blank? .present? in Ruby on Rails

    We get confused when there are many options to choose from. Same is the case when it comes to use an ...