代码改变世界

《WF编程》系列之36 - 自定义活动:如何创建自定义活动?活动的组合

2007-12-07 09:56  Windie Chai  阅读(...)  评论(...编辑  收藏

5.2 如何创建自定义活动?

有两种方式可以创建自定义活动,即通过组合的方式和使用继承的方式.
组合是一种简单的创建工作流的方式.我们在设计器中拖拽并配置活动的属性,然后把这个自定义活动封装成一个程序集,这样就可以供其它工作流项目使用了.这种方式的优点是快速并且简单.
使用继承的方式来创建自定义活动,我们需要编写一个类,并使其继承Activity类.也可以继承自Activity的子类从而获得更多的功能.我们可以自定义活动的设计视图,验证,序列化和代码生成.继承的方式允许我们对自定义活动进行更深层次的控制,并且提供了使用自定义代码来扩展Windows Workflow的途径.

5.3 活动的组合

让我们再回到经典的bug跟踪工作流,看看自定义活动能带给我们什么样的帮助.bug跟踪工作流需要针对bug去请求一份文档.为了这个文档,工作流需要和本地服务进行通信,所以它将实现以下接口:
[ExternalDataExchange]
interface IBugService
{
bool RequestUpload(Guid id, string userName);
event EventHandler UploadCompleted;
}
需要文档的工作流首先使用CallExternalMethod活动来调用ResuestUpload方法.紧接其后,工作流会使用HandleExternalEvent活动来等待UploadCompleted事件.我们需要插入并配置这两个活动到每一个需要请求文档的工作流中.所以我们的目标就是用一个自定义活动来替换这两个活动.
首先,我们创建一个工作流活动库,在New Project对话框中,选中Workflow Activity Library项目类型.这个项目类型会引用所有WF相关的程序集,并且可以生成的程序集可以被其它工作流项目引用.

活动库项目包含一个默认的活动(Activity1.cs),我们可以将其重命名为GetUpload.cs.这个活动使用纯代码的方式来编写.在第二章我们讨论过纯代码,纯XAML以及结合XAML和代码隐藏类这三种编写工作流的方式,这三种方式也同样适用于编写自定义活动.我们可以在New Item对话框中使用这几种方式添加新的活动.
在默认的情况下,自定义活动的根活动是一个SequentialActivity.在设计视图,我们可以从工具箱拖拽活动到设计器中.在下图中,我们添加了一个CallExternalMethod活动和一个HandleExternalEvent活动,然后配置这两个活动使它们分别调用RequestUpload方法和操作UploadCompleted事件.此时我们不需要配置任何方法和事件的参数.

现在编译一下活动库,会生成一个程序集文件.下一步,我们可以创建新的工作流项目并在其中使用这个程序集.在Visual Studio的File菜单中,点击Add>New Project.选择Sequential Workflow Console Application作为项目模板并为项目取名为Chapter5_workflows.想要使用刚才创建的自定义活动,我们需要右键单击新建的项目并选择Add Reference.在Projects选项卡中选择第一步时创建的活动库项目.
当我们开始设计工作流时,Visual Studio会找到我们引用的自定义活动并将其添加到工具箱中.在工作流设计视图中,我们的工具箱就会如下图所示:

在设计视图中,添加一个GetUploadActivity.注意我们的自定义活动内部的活动会显示出锁死的图标,这表示我们不能向通过组合的方式创建的自定义活动内部添加子活动(除非这个活动是空的).

现在才发现,我们不能修改自定义活动内部活动的属性.因为一个编译后的组合活动会变成一个”黑盒子”.我们无法向这个黑盒子中添加子活动,也无法删除或者修改里边的子活动.作为自定义活动的设计人员,需要认识到这一点.我们并不希望开发人员改变CallExternalMethod活动的InterfaseType或MethodName属性.因为改变这些属性可能会破坏GetUploadActivity原有的功能.我们的自定义活动需要保持完整性.
而对于自定义活动的使用者来说,黑盒引发了一个问题.在工作流内部,我们需要访问CallExternalMethod活动的id和userName参数,从而将正确的数据传递给宿主.如果工作流无法访问这些属性,那么自定义活动也就没有使用价值了.
作为自定义活动的编写人员,我们需要做的就是让这个组件可以使用.
下一节,让我们打开黑盒子,看看里边究竟有什么.