这两个世界的交互使用了workflow提供的两个活动:CallExternalMethod 和HandleExternalEvent ,分别使用在workflow传递数据给Host和Host传递数据给workflow两个方向上。
CallExternalMethod 就是通过服务接口中定义的事件将信息在事件参数中传递给Host,事件在Host中注册处理程序,处理参数(传递过来的数据)。
HandleExternalEvent 就是向外部提供一个激活自己事件的方法,供外界调用,同时传递参数给workflow,在工作流中还要写事件对应的处理代码,事件的Handler代码,接收、处理外部传过来的参数。
sharepoint工作流预定义了很多任务相关的活动,CreateTask就是一个 CallExternalMethod ,在工作流中可以操作sharepoint对象模型,创建任务,相当于向Host中的sharepoint发送信息,信息就是新建一个工作流任务。OnTaskChanged就是一个HandleExternalEvent ,就是Host向工作流发送消息,工作流任务改变了,在工作流中要做出响应。可以说一个工作流任务是属于一个工作流实例的,工作流任务的修改和删除都要经过Host来通知工作流,就是使用sharepoint工作里组件中要On开头的那些组件,也就是通过交互方法提供的方法来激活工作流对应的事件,然后由工作流来做出响应。
Pitfall容易犯的错误:
1、在sharepoint中操作未提交的列表项
对于还没有提交的列表或者列表项,不要使用对象模型来调用它们。记住要首先持久化他们,在获取他们之前,要使用event handler或者delay。例如,如果你创建工作流任务,任务列表的列表项在你使用event handler或者delay睡觉工作流之前是不存在的。使用工作流服务没有问题,但是在睡觉工作流之前不要使用对象模型操作列表项。
原文地址:
http://www.codeproject.com/KB/WF/host_wf_comm_p3.aspx
在第二部分我们知道了在工作流启动的时候,Host如何传递初始化数据给工作流,同时工作流返回数据给Host。但是你还有可能有更复杂的情况,你必须发送消息给工作流,不是在初始化的时候,而是在运行的过程中,或者是在工作流运行的过程中多次发消息给工作流。这些需求你都可以用HandleExternalEvent 活动来实现。
使用HandleExternalEvent 活动我们可以停止工作流,然后等待一个外部的事件发生,在收到事件之后,工作流可以继续执行下面的过程。
HandleExternalEvent 活动可以获取来自Host的信息,通过事件的参数。
如果我们比较CallExternalMethod 和HandleExternalEvent,我们可以发现他们都调用了另一个应用的另一个线程的一段代码。前面的是调用方法,后面的是等待事件发生。
就像你看到的,在用户单击应用程序的按钮的时候,你每次必须向工作流提供命令或者数量,很显然你不能在初始化工作流的时候提供这些信息。
HandleExternalEvent 活动等待定义好的外部事件,你必须确保数据在正确的时候被接收。数据使用CallExternalMethod 返回,这个活动在第二部分中已经解释过了。
为了实现这个交互我们需要满足一个好像CallExternalMethod 的模式,但是我们需要定义一个外部事件。简单来说,我们需要下面的步骤:
创建下面的接口和类:
1、一个被CallExternalMethod 调用的接口和方法,HandleExternalEvent 活动的事件处理
2、实现接口的一个类,要实现被CallExternalMethod 调用的类方法,就是发送数据给Host,HandleExternalEvent 活动的事件处理
3、你要有一个专门的事件参数用来给工作流发送信息,参数被外部事件使用,这个参数有一个需要GUID的构造函数,这个GUID是要交互的工作流实例的guid。在我们的例子中可能不是很重要,因为只有一个工作流实例,但是如果同时有很多的工作流实例,它将扮演很重要的角色。
4、实现参数类接受被CallExternalMethod 调用的方法传递的数据
在Host应用程序中要实现下面的步骤:
1、创建一个ExternalDataExchangeService ,并在工作流运行时中注册
2、创建一个CommunicationCalculator 实例,然后添加到上一步注册的服务中
3、如果你使用事件驱动工作流到Host的交互,在你的Host代码中处理事件
4、为了和工作流交互,你一定要激活外部的事件,然后传参数给他。
在工作流中:
1、拖拽一个CallExternalMethod 活动
2、设置他的接口和调用方法。
3、对于每一个Host 的事件都要有一个HandleExternalEvent 来接收事件,对于我们这个就只有一个就可以
4、配置HandleExternalEvent 的接口和事件
5、接受一个事件,你应该定义一个公共的CalculadorEventArguments 参数来接受外部事件带来的信息
上面是类的关系图,还有一些解释我会在后面补上,现在有事先暂停一下,不好意思了。