Workflow and the Outside world
There are three way we can comunicate with workflow:
- Event(将外面的数据传递给WF InstanceEvents are used for sending data to a workflow)
- Method(把WF Instance里面的数据传递给Host应用程序 is used by workflows to send data to the host application)
- Parameters(通过参数传递给WF Instance)
Workflow Instance Lifecycle Events
Name | Description |
WorkflowAborted | Occurs when an instance aborts. The WorkflowInstance class includes an Abort method to abort a workflow. |
WorkflowCompleted | Occurs when the instance completes, and includes a WorkflowCompletedEventArgs parameter to retrieve any output parameters. |
WorkflowCreated | Occurs after we create a workflow with the WorkflowRuntime's CreateWorkflow method. |
WorkflowIdled | Occurs when a workflow enters an idle state. A workflow becomes idle when it is waiting for a timer or external event to take place, for instance. |
WorkflowLoaded | Occurs when a persistence service has restored a workflow instance into memory to continue execution. |
WorkflowPersisted | Occurs when a persistence service persists a workflow. A workflow may persist and then unloaded from memory when it is in the idle state and waiting for an event. |
WorkflowSuspended | Occurs when the runtime suspends a workflow, typically due to a SuspendActivity in the workflow. |
WorkflowResumed | Occurs when workflow execution continues after a suspension. |
WorkflowStarted | Occurs when a workflow firsts starts execution. |
WorkflowTerminated | Occurs when a workflow terminates, typically due to an unhandled exception. WorkflowTerminatedEventArgs will include the exception object. |
WorkflowUnloaded | Occurs when the runtime unloads a workflow from memory, typically due to the workflow being idle. |
采用Event和Method实现WF与Hosting之间的通讯,需要一下几个步骤:
- Service Contracts服务契约,也就是服务的接口。需要定一个Interface,里面定义通讯所必需的方法,事件以及相应的参数,这里要强调的一点是,因为传递参数要跨应用程序域,所以参数必需是可以序列化的。该接口需要有一个[ExternalDataChange]特性。下面是一个Service Contracts的例子:
[ExternalDataExchange]
interface IBugFlowService
{
void AssignBug(Bug bug);
event EventHandler<BugAddedArgs> BugAdded;
}在事件中传递的事件参数必需是继承自ExternalDataEventArgs类的。
- Service的实现,需要实现1中定义的Service Contracts,这个实现没有很特别的。这里面要明晰两个概念就是,方法(Method)是WF Instance向Hosting中传递数据,事件(Event)是Hosting向WF Instance中发送数据。
- Workflow实现。上面我们讲了,方法是WF向外发送数据,事件是向WF发送数据。这些分别是用HandleExternalEventActivity 和CallExternalMethodActivity来实现的,HandleExternalEventActivity侦听Hosting中注册的LCS事件,当它所订阅的事件触发时,它能捕获事件,并做相应的处理。CallExternalMethodActivity是调用Hosting中的LCS的方法,并把数据传递给Hosting。
下面我对上面的HandleExternalEventActivity和CallExternalMethodActivity做一下分析。
HandleExternalEventActivity处理外部事件的活动
该活动既然是要处理外部事件,而这个外部事件是由注册到WF Runtime中的ExternalDataExchangeService来触发的。那么我们需要知道该活动是侦听哪个Service的哪个事件,事件传递的参数又要做如何处理等。
一个HandleExternalEventActivity必需设置的两个属性分别是InterfaceType和EventName。InterfaceType是要指定处理的是哪个Service,它必须是标注又ExternalDataChange特性的Interface。 EventName就是它里面相应的事件。当你指定事件后,VS会自动增加一个Parameter参数组,其中一个参数是e,是相应Event对应的事件参数,需要你指定事件参数的处理,你可以把事件参数赋值到WF中的一个字段或者属性。
HandleExternalEventActivity有一个事件,就是Invoked,这个就是用来处理外部的事件的,其中的事件参数就是相应Service传递进来的参数,可以在这个事件的处理程序中对Hosting传递进来的数据进行处理。
CallExternalMethodActivity调用外部的方法Activity
同样的,CallExternalMethodActivity也是调用注册到WF Runtime中的Service的方法,同样的思路,我们需要指定对应的InterfaceType以及MethodName。相应的Method的参数也需要进行指定,可以将Method的参数指定到WF的相关的属性(Property)或者字段(Field)。CallExternalMethodActivity在调用外部方法之前,会触发一个事件MethodInvoking,我们可以在这个事件中为外部方法的调用做一些准备工作,比如组织数据等。
Hosting的实现
下面是一个典型的通过LCS实现WF与Hosting之间通讯的例子:
//定义并初始化一个数据交换服务(ExternalDataExchangeService) ExternalDataExchangeService dataService; dataService = new ExternalDataExchangeService();
//把该数据交换服务添加到runtime中 runtime.AddService(dataService);
//实例化一个Service Contract的实现,并把它添加到数据交换服务中
BugFlowService bugFlow = new BugFlowService();
dataService.AddService(bugFlow);
//启动工作流实例
WorkflowInstance instance;
instance = runtime.CreateWorkflow(typeof(BugFlow));
instance.Start();
//触发外部事件。
Bug bug = new Bug(1, "Bug Title", "Bug Description");
bugFlow.CreateBug(instance.InstanceId, bug);
下图是Programming Windows Workflow Foundation中的关于WF Instance与外界进行通讯的例子的示意图。可以看出:
1.WF Instance是通过ExternalDataExchangeService 来作中介实现数据交换,首先要把LCS 的实例添加到ExternalDataExchangeService中,而ExternalDataExchangeService 实例也添加到Runtime的Service中(通过AddService);
2.WF通过HandleExternalEventActivity相应外部的事件,内外部传递的参数必需是可序列化的。WF通过CallExternalMethodActivity来调用外部的方法。