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

     原文地址:
      http://www.codeproject.com/KB/WF/host_wf_comm_P4.aspx
       到目前为止我们已经知道了Host和工作流交互的重点,现在我们要做一点小东西,使得我们的工作容易一些,如何用面向对象来组织我们的工作。
      从前面的章节中我们看到,使用CallExternalMethod 和HandleExternalEvent活动来实现这些是可以的,但是如果我们有一个复杂的工作流,该使用那些活动可能就变得迷惑了。
      workflow的SDK提供了一个自动添加所需CallExternalMethod 和HandleExternalEvent活动的工具,可以减轻我们的工作,使得工作流很容易理解。
      wca.exe直接使用从dll中获取的必要信息来创建常用活动,dll是我们定义的外部交互接口。工具需要设置一些选项来生成常用行为。因为控制台程序通常比较复杂,因为数据的路径或者程序自己越来越复杂,作者写了一个小winform工具,可以免费获取。WWCA.ZIP 
      wf11.JPG
      在使用这个小程序之前,要存储wca.exe的目录(可以参照C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin),在wwca.exe的配置菜单中设置。
      如你看到的,工具只需要你的自定义交互服务的目录作为输入,他就会很容易的检查不同的输入参数和选项。
      在前面我们开发的在Host中迁入工作流和交互服务没有任务的面向对象。那是因为我们的交互服务没有包装起来。
      在这篇中,我们将创建一个交互管理类来驱动所有和交互有关系的。
      好的,我们使用一个简单的程序控制一个简单的值。值可以被一个按钮驱动,另外一个按钮来驱动打开或者关闭这个值的状态。
      有一条简单的业务规则,当值是关闭状态的话,值可以power off;如果值是打开状态  ,你不可以power off。
      我们将使用一个状态机工作流来控制值得状态,用户的接口是一个winform的程序。
      wf22.JPG
      上图是这个程序的架构。
      代码开发
      1、交互管理器
      从上面的图中我们可以看到Host是如何和工作流进行交互的 。
            从工作流到Host:我们需要一个外部方法来返回状态信息给Host,你可以定义一些返回信息为字符串,例如,CLOSE OPEN EXIT INIT
            从Host到工作流:这里你有两种选择,每个状态改变对应一个事件或者事件带一个新状态作为参数
      我在这里选择每一个状态对应一个事件,这样我就不需要创建一个特殊的事件参数,我可以直接使用ExternalDataEventArgs 参数,因为我在参数中不需要传递自定义的信息。
      我们需要声明三个事件,分别是:open,close,exit。不需要声明init,因为你创建工作流的时候你就是init。
      首先创建下面的接口

[ExternalDataExchange]
public   interface ICommunicationValve
{
#region  Communication WF -> Host
  ///   <summary>
   /// Used by CallExternalEvent Argument to pass the valve
   /// status to Host
   ///   </summary>
  ///   <param name="status"> Actual statis for valve </param>
   void  StatusValve(Guid wfGuid,  string status);
#endregion

#region  Communication Host -> WF
  ///   <summary>Use to pass the valve operation to workflow
   /// </summary>
   event  EventHandler < ExternalDataEventArgs > CloseValve;
   ///   <summary>Use to pass the valve operation to workflow
   /// </summary>
   event  EventHandler < ExternalDataEventArgs > Exit;
   ///   <summary>Use to pass the valve operation to workflow
   /// </summary>
   event  EventHandler < ExternalDataEventArgs > OpenValve;

#endregion

}// end ICommunicationValve

 

接下来要做的就是实现这个接口,因为我们这里是一个winform程序,因此我们需要在StatusValve 方法中实现一个内部的事件,通过事件传递信息给表单。

public   class CommunicationValve : ICommunicationValve
{
   #region  WF -> Host Communication
  public   event  EventHandler < ExternalValveEventArgs >
  EventValveStatus;

  ///   <summary>
   /// Used by CallExternalEvent Argument to pass the valve 
   ///status to Host
   ///   </summary>
  ///   <param name="status"> Valve status OPEN / CLOSE / EXIT </param>
   public   void  StatusValve(Guid wfGuid,  string status)
  {
      if  (EventValveStatus  !=   null)
     {
        ExternalValveEventArgs e  =   new ExternalValveEventArgs(wfGuid);
        e.Status  = status;
        EventValveStatus( this , e);  // Raise the event
  }

}

#endregion

#region  Host -> WF
  ///   <summary>
   /// Use to pass the valve operation to workflow
   ///   </summary>
   public   event  EventHandler < ExternalDataEventArgs > CloseValve;

   ///   <summary>
   /// Use to pass the valve operation to workflow
   ///   </summary>
   public   event  EventHandler < ExternalDataEventArgs > Exit;

   ///   <summary>
   /// Use to pass the valve operation to workflow
   ///   </summary>
   public   event  EventHandler < ExternalDataEventArgs > OpenValve;

#endregion

#region  Auxiliar procedures

  ///   <summary>
   /// Raise the event Exit
   ///   </summary>
  ///   <param name="instanceId"> workflow instance </param>

  public   void RaiseExit(Guid instanceId)
  {

      if  (Exit  !=   null)
     {
        ExternalDataEventArgs e  =   new ExternalDataEventArgs(instanceId);
        e.WaitForIdle  =   true;
        Exit( null, e);
     }
  }

   ///   <summary>
   /// Raise the event Open
   ///   </summary>
  ///   <param name="instanceId"> workflow instance </param>
   public   void RaiseOpen(Guid instanceId)
  {
     if  (OpenValve  !=   null)
    {
       ExternalDataEventArgs e  =   new ExternalDataEventArgs(instanceId);
      OpenValve( null, e);
    }
  }
   ///   <summary>
   /// Raise the event Close
   ///   </summary>
  ///   <param name="instanceId"> workflow instance </param>
   public   void RaiseClose(Guid instanceId)
  {
     if  (CloseValve  !=   null)
    {
       ExternalDataEventArgs e  =   new ExternalDataEventArgs(instanceId);
       CloseValve( null, e);
    }
  }
#endregion
} // end CommunicationValve

      如你所看到的,我们直接在实现接口的类中包装了激发事件的方法,这样你就不需要在外部激发事件。
      就像你在前面的章节中看到的,你需要在工作流运行时中注册这个服务为你的交互服务。那么创建一个包装这些活动的对象是一个好主意。这里我们创建一个交互管理类,这个类一定只能包含一个CommunicationValve 类的实例,一个工作流运行时的引用。
      代码如下
public   class CommunicationManager 
{

   ///   <summary>
   /// Single onject of the communicationValve class.
   ///   </summary>
   private   static  CommunicationValve Comvalve  =   null;

   ///   <summary>
   /// Reference to the workflow runtime.
   ///   </summary>
   private  WorkflowRuntime runtime  =   null;

   ///   <summary>
   /// Return the CommunicationValve instance.
   ///   </summary>
   public CommunicationValve Valve
  {
     get
      {
         return Comvalve;
      }
  }

   ///   <summary> Constructor Communication manager </summary>
  ///   <param name="wfRuntime"> Runtime instance </param>
   public CommunicationManager(WorkflowRuntime wfRuntime)
  {
    runtime  = wfRuntime;
     if  (Comvalve  ==   null)
    {
      Comvalve  =   new CommunicationValve();
    }
  }

   ///   <summary>
   /// Procedure to register the communication service.
   ///   </summary>
   public   void RegisterCommunicationService()
  {
     // Declare a ExternalDataExchangeService class
    ExternalDataExchangeService dataservice  =   new
    ExternalDataExchangeService();
    // Add to workflow runtime
    runtime.AddService(dataservice);
     // Add to the ExternalDataService
    dataservice.AddService(Comvalve);
  }
} // end CommunicationManager


      我们可以应用一个假象概念,在这个管理类中声明一个触发ValveCommunication 类中事件的方法,而不是直接调用ComValve 实例。
      我们已经有了自己的管理类,全部的类关系图如下图
wf33.JPG
2、应用工作流
      创建一个状态机工作流库项目,我们要做的第一布就是建立自定义行为。
      打开wwca.exe程序,选择在前面创建的dll,也就是CommunicationManager。选择输出工作路的路径,选择option中的include sender ,填写   在你的项目中使用的命名空间。
      然后选择【action】-》【Execute wca】,如果操作正确的话,在下面的结果中就会看见内容,wca.exe发送的控制信息。
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值