宿主和工作流:两个世界的交互 II(工作流给Host传递数据)

  我们理解了如何在启动的时候从Host传递数据给工作流,如果我们不需要从工作流返回数据的话,前面的工作就足够了。但是很多时候,我们都想要从工作流中返回一些处理的数据。
    微软的工作流框架为我们提供了一个活动CallExternalMethod,来完成这样一件事。
       回想上一章的列子,我们的Host程序从计算机中读取一个文件,读取一定数量的字符,在工作流中显示内容。在程序中我们要传递两个参数(一个是文件的路径,一个是从文件返回的字符数量),在工作流用MessageBox显示内容。现在,我们需要在Host的控制台中显示这些从工作流返回的信息,而不是在工作流的MessageBox中显示。如下图所示
wf5.JPG
       为了实现从工作流传递数据给Host,微软提供一个专门用于这个功能的活动,叫做CallExternalMethod,这是一个好消息,坏消息是我们必须自定义一个和这个活动交流的服务模式。
      交互服务模式是另外一种服务,你必须创建一个服务的接口,实现这个接口,然后在工作流运行时 Workflow runtime 中注册实现这个接口的实例。你可以实现你想要的交互,事件或者poll (这个单词不知道如何来翻译),但是你必须满足CallExternalMethod的要求。简单来说看你需要实现下面的代码结构。

        创建下面的类和接口:
      1、创建一个被CallExternalMethod活动调用的接口和相应的方法
      2、一个实现上面的接口的类。在类中,我们要实现接口中定义的被CallExternalMethod调用的方法,方法的内容就是你的工作流发送数据到Host。
      3、如果你要用事件来驱动交互,你必须实现一个继承自EventArgs 的类,用来存储你要发送给Host的信息。

      在Host程序中要做下面的事情:
      1、你应该创建一个ExternalDataExchangeService 类的实例,并在工作流运行时中注册它。
      2、你也要在数据服务类(ExternalDataExchangeService) 中的注册你的自定义的交互服务。
      3、如果你使用事件驱动交互,你还要在Host程序中进行事件的处理。
      
      在工作流中:
      1、你必须有一个叫做CallExternalMethod的活动
      2、在CallExternalMethod活动中注册一个接口和调用的方法
下图是类的结构
wf6.JPG

你可以看见CallExternalMethod活动在另外一个线程中调用了的方法,当方法执行的时候,在Host中我们就会看到消息。
       下面开始我们的代码设计,一步一步的使用CallExternalMethod来实现。
1、创建下面的接口和类
       你可以在单独的类库中创建接口和类,简单起见就在当前项目下面创建。

namespace CommunicationCallExternalMethod
{
    /// <summary>
    /// You MUST to mark the interface with the header ExternalDataExchange
    /// to identify the interface as the communication interface.
    /// </summary>
    [ExternalDataExchange]
    public interface ICommunicationService
    {
         /// <summary>
        /// This method must be call by the CallExternalMethod Activity
        /// to transfer the information to the console host application
        /// </summary>
        /// <param name="response">Data to send to console</param>
        void SendDataToHost(string response);
    }
}


从名字上面来看,很容易明白,接口的方法用来给Host发送数据。特性[ExternalDataExchange]说明类型中的方法可以被工作流调用。
2、实现上面接口的类
在类中你可以将方法实现为简单的传递数据给Host,Host poll类实例,或者你也可以用事件来异步的获取数据。
    在我们的代码中我们实现了事件,我们将数据通过工作流事件的参数传递。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommunicationCallExternalMethod
{
    
     ///   <summary>
     /// Implement the interface
     /// This implementation is made to comunicate WF -> Host
     ///   </summary>
     public   class CommunicationService: ICommunicationService
    {

         ///   <summary>
         /// Event to communicate the host the result.
         ///   </summary>
         public   event  EventHandler < SendDataToHostEventArgs > SendDataToHostEvent;
         ///   <summary>
         /// Implement the external Method
         ///   </summary>
        ///   <param name="response"> response to host </param>
         public   void  SendDataToHost( string response)
        {
            SendDataToHostEventArgs e  =   new SendDataToHostEventArgs();
            e.Response  = response;
            EventHandler < SendDataToHostEventArgs >  sendData  =   this.SendDataToHostEvent; 
             if  (sendData  !=   null)
            {
                sendData( this, e);
            }
        }
    }
}

从上面我们可以看出来,方法只是简单的将数据传递给事件的参数,并且触发事件。事件参数的定义如下

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Workflow.Activities;

namespace CommunicationCallExternalMethod
{
     public   class SendDataToHostEventArgs: EventArgs
    {
         string  _response  =   string.Empty;
         ///   <summary>
         /// This property is used to pass in the Event the response to host
         ///   </summary>
         public   string Response
        {
             get
            {  return _response; }
             set
            { _response  =  value; }
        }

    }
}

在我们的例子中创建了三个类,分别是:
  • SendDataToHostEventArgs.cs
  • CommunicationService.cs
  • ICommunicationService.cs

3、注册我们自定义的交互服务作为工作流的ExternalDataExchangeService外部数据交互服务

注册过程是在工作流运行时中进行,可以参照下面的代码

ExternalDataExchangeService dataservice  =   new ExternalDataExchangeService();
// Add to workflow runtime
workflowRuntime.AddService(dataservice);
// Declare our CommunicationService instance
CommunicationService cservice  =   new CommunicationService();
// Add to the ExternalDataService
dataservice.AddService(cservice);
// Add a handler to Service Event
cservice.SendDataToHostEvent  +=   new  EventHandler < senddatatohosteventargs > (cservice_SendDataToHostEvent);

第一步是注册交互服务,接下来是注册事件的处理程序

4、在工作流设计界面进行设置
就用上一章我们建立的工作流就可以,拖拽一个CallExternalMethod  活动到设计界面上来,设置如下

wf7.JPG
选择InterfaceType 属性为ICommunicationService,在MethodName属性中选择接口的SendDataToHost方法,将方法的参数response,也就是消息的内容绑定到工作流的一个属性上来,可以实现动态绑定更新工作流的属性。

使用CallExternalMethod 活动, 从工作流传递数据给Host的基本步骤如下:
1、创建下面的接口和类
      1)一个被CallExternalMethod 活动调用的接口方法,并且标记接口为[ExternalDataExchange]
      2)一个实现接口的类,类中实现被[CallExternalMethod ]活动调用的方法,
2、在Host程序中做下面的事情
      1)为工作流运行时注册一个ExternalDataExchangeService类 的实例
              
               ExternalDataExchangeService dataservice = new ExternalDataExchangeService();
                //Add to workflow runtime
                workflowRuntime.AddService(dataservice);
      2)为ExternalDataExchangeService类 的实例添加交互的实例
              
               CommunicationService cservice = new CommunicationService();
                //Add to the ExternalDataService
                dataservice.AddService(cservice);
                //Add a handler to Service Event
      3)如果你使用事件驱动交互,在你的Host程序中要定义事件处理
 cservice.SendDataToHostEvent += new EventHandler<SendDataToHostEventArgs>(cservice_SendDataToHostEvent);
  3、在工作流中
      1)拖拽一个CallExternalMethod 活动到设计器中,
      2)设置CallExternalMethod 活动的接口和方法,绑定参数

      现在为止,你有了一个从Host到工作流的单向交互,但是你还是有局限,直到现在你只是知道如何给工作流传递初始化数据,但是你还不知道在如何随时给工作流传递参数?在下一章我们将会讲到这些。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值