状态机工作流.实列.报销审批流程(三)

接上篇文章 “状态机工作流.实列.报销审批流程(二) ”
     本文主要讲述,如何实现一个自定义的,状态保存服务,原本是要写一个保存到Oracle 数据库的,状态保存服务的、不过家里没有 Oracle ,
  而且现在主要是为了练习一些实列,底层的东西是需要好好设计一下的,现在在还没有对状态保持等WF服务了解到一定的程度所以这里子凭自己的感觉,和看 ms 的代码,和一些网友的东西作也许有很多不对的地方、还需以后更正......
  不过代码既然都发了还是需要写点啥的对吧.

涉及技术
  WorkflowPersistenceService  的实现
  对象序列化(这个没啥好讲的,打VC5 时代就有的东西,园子里也有好多文章讲解)

类设计/说明(Xom.WF.ManagerWorkflowLibrary 项目)
  1. FileWorkflowPersistenceService

      就是持久化服务了,在 web 项目 Global 里加载的,继承 WorkflowPersistenceService,实现 IPendingWork

    WorkflowPersistenceService  实现

    • Activity LoadCompletedContextActivity(Guid scopeId, Activity outerActivity)
      读取一个已经完成的 Activity(这个还不知道啥时候调用)

    • Activity LoadWorkflowInstanceState(Guid instanceId)
      读取一个没完成的 activity 状态

      代码

      ///   <summary>
              
      ///  载入实例 activity 状态
              
      ///   </summary>
              
      ///   <param name="instanceId"></param>
              
      ///   <returns></returns>
               protected   override  System.Workflow.ComponentModel.Activity LoadWorkflowInstanceState(Guid instanceId)
              {

                  Debug.WriteLine(
      " LoadWorkflowInstanceState " );
                  
      byte [] buffer1  =   null ;
                  FileTools.LoadActivity(_mainPath, instanceId, 
      out  buffer1);            
                  
      return  WorkflowPersistenceService.RestoreFromDefaultSerializedForm(buffer1,  null );
              
              
              }


    • SaveCompletedContextActivity(Activity activity)
      保存一个已经完成的 Activity(这个还不知道啥时候调用)

    • SaveWorkflowInstanceState(rootActivity, bool unlock)
      保存一个没完成的 Activity,在我的列子里 unlock 好像永远是 true

      代码

      ///   <summary>
              
      ///  保存实例
              
      ///   </summary>
              
      ///   <param name="rootActivity"></param>
              
      ///   <param name="unlock"></param>
               protected   override   void  SaveWorkflowInstanceState(System.Workflow.ComponentModel.Activity rootActivity,  bool  unlock)
              {
                  Debug.WriteLine(
      " SaveWorkflowInstanceState: "   +  unlock);
                  
      if  (rootActivity  ==   null )
                  {
                      
      throw   new  ArgumentNullException( " rootActivity " );
                  }
                  
      // 取得当前工作流状态
                  WorkflowStatus status  =  WorkflowPersistenceService.GetWorkflowStatus(rootActivity);
                  
      // 不太明白英文不好不过 ms 保存了咱也保存 (Indicates whether the given activity is blocked)
                   bool  blocked  =  WorkflowPersistenceService.GetIsBlocked(rootActivity);
                  
      // 停止的信息
                   string  info  =  WorkflowPersistenceService.GetSuspendOrTerminateInfo(rootActivity);
                  
      // 状态id
                  Guid stateId  =  (Guid)rootActivity.GetValue(Activity.ActivityContextGuidProperty);
                  
      // 状态存实体类
                  PendingWorkItem item1  =   new  PendingWorkItem();
                  
      // 标示,调用的是 SaveWorkflowInstanceState 函授
                  item1.Type  =  PendingWorkItem.ItemType.Instance;
                  
      // 当前的 WorkflowInstanceId
                  item1.InstanceId  =  WorkflowEnvironment.WorkflowInstanceId;
                  
                  
      byte [] buffer1;
                  
      if  ((status  !=  WorkflowStatus.Completed)  &&  (status  !=  WorkflowStatus.Terminated))
                  {
      // 如果不是停止或出错就序列化
                      buffer1  =  WorkflowPersistenceService.GetDefaultSerializedForm( rootActivity );
                  }        
                  
      else
                  {
                      buffer1 
      =   new   byte [ 0 ];
                  }
                  
      // 把一系列数据放到 PendingWorkItem
                  item1.SerializedActivity  =  buffer1;
                  item1.Status 
      =  ( int )status;
                  item1.Blocked 
      =  blocked  ?   1  :  0 ;
                  item1.Info 
      =  info;
                  item1.StateId 
      =  stateId;
                  item1.Unlocked 
      =  unlock;
                  
                  TimerEventSubscription subscription1 
      =  ((TimerEventSubscriptionCollection)rootActivity.GetValue(TimerEventSubscriptionCollection.TimerCollectionProperty)).Peek();
                  item1.NextTimer 
      =  (subscription1  ==   null ?  DateTime.MaxValue : ((DateTime)subscription1.ExpiresAt);
                  
      if  (item1.Info  ==   null )
                  {
                      item1.Info 
      =   "" ;
                  }

                  
      // 放到 WorkBatch 里,由于实现了 IPendingWork 所以可以把你的自定义实体类放到 WorkBatch 中
                  
      // 等 UnloadOnIdle 返回 true 时会调用 IPendingWork.Commit 统一处理
                  WorkflowEnvironment.WorkBatch.Add( this , item1);
                  
              }


    • bool UnloadOnIdle(System.Workflow.ComponentModel.Activity activity)
      询问持久化服务是否空闲,是否可以重内存中卸载工作流到持久化,我的代码始终是true 的

    • UnlockWorkflowInstanceState(System.Workflow.ComponentModel.Activity rootActivity)
      解锁一个正在运行的工作流,****这个我发的代码里处理是不对的,我把他给按Completed 处理的大家注意***

    IPendingWork 接口实现

    • Commit(System.Transactions.Transaction transaction, System.Collections.ICollection items)
      当 UnloadOnIdle 为 true 时会执行本操作,进行序列化如果不实现 IPendingWork 应该在 SaveWorkflowInstanceState 里直接保存

      代码

      public   void  Commit(System.Transactions.Transaction transaction, System.Collections.ICollection items)
              {
                  Debug.WriteLine(
      " Commit " );
                  
      foreach  (PendingWorkItem item1  in  items)
                  {
                      
      switch  (item1.Type)
                      {
                          
      case  PendingWorkItem.ItemType.Instance:
                              {
      //

                                  
      if  (item1.Status  ==   1   ||  item1.Status  ==   3
                                  {
      // Completed or Terminated
                                   
      // 如果是出错或完成的就更名为 .bak 文件
                                      FileTools.BakPendingWorkItem( this ._mainPath, item1.InstanceId);
                                  }
                                  
      else
                                  {
      // 如果是正常的工作流 就保存为 ,<Guid>.xact 文件名方式保存到 MainPath 中
                                      FileTools.SavePendingWorkItem( this ._mainPath, item1);
                                  }    
                                                                  
                                  
      break ;
                              }
                          
      case  PendingWorkItem.ItemType.CompletedScope:
                          {
                                  
      throw   new  ApplicationException( " Commit case PendingWorkItem.ItemType.CompletedScope " );
                                  
                          }
                          
      case  PendingWorkItem.ItemType.ActivationComplete:
                          {
                                  FileTools.BakPendingWorkItem(
      this ._mainPath,item1.InstanceId);  // 这里的处理是不正确的应该是解锁我以前理解错了
                                   break ;
                          }
                      }
                      
                      
      //
                  }
              }

    • Complete(bool succeeded, System.Collections.ICollection items)
      持久化完成

    • bool MustCommit(System.Collections.ICollection items)
      是否需要 commit,我的代码里始终是 true

    类中的其他函数
    • 构造函数
      没啥就是取了一个 保存的路径,实现了 FileWorkflowPersistenceService(NameValueCollection parameters) 就可以重配置文件传参数了
    • GetAllWorkflows()
      取得所有没完成的 Activity  就是循环目录里所有的 *.xact

  2. FileTools

      这个文件都是一些序列化或反序列化的函授方法不再详细说明了,各位也都能看懂估计

  3. PendingWorkItem

      
    状态保存用的实体类,就是保存些数据啥的,看ms 代码得来的

    代码


      
    ///   <summary>
        
    ///   保持状态的模块类
        
    ///   </summary>
        [Serializable]
        
    public   sealed   class  PendingWorkItem
        {
            
    //  Methods
             public  PendingWorkItem()
            {
                
            }


            
    // 看提示是 Indicates whether the given activity is blocked. 不知道啥意识不过ms 写了咱也留着
             public   int  Blocked;
            
    // 信息
             public   string  Info;
            
    // 工作流运行时的 Guid
             public  Guid InstanceId;
            
    public  DateTime NextTimer;
            
            
    // 序列化的工作流
             public   byte [] SerializedActivity  =   new   byte [ 0 ];
            
    //
             public  Guid StateId;
            
    // 工作流的状态Guid
             public   int  Status;
            
    // 状态,标示是调用的那个 WorkflowPersistenceService 的函数
             public  ItemType Type;
            
    // 是否是锁定的
             public   bool  Unlocked;

            [Serializable]
            
    public   enum  ItemType
            {
                Instance,  
    // 正常的状态
                CompletedScope,  // 完成
                ActivationComplete  // 激活
            }

        }



程序运行流程是这样的
(自己的见解,不是官方的,Windows SDK 太大计算机已经没地方安装了,
再说就算安装了也找不到英文不好基本就是小学英语水平,还有版本老更新受不了....)
  1. 在 workflowRuntime 添加自定义 WorkflowPersistenceService (在web项目里 Global.asax里有列子)
  2. 当 工作流引擎需要持久化 下面是函数的调用顺序
    UnloadOnIdle //看看持久化服务空闲不如果返回 true 继续
    SaveWorkflowInstanceState //调用保存状态寒酸
    MustCommit //看看是否需要 commit 如果返回true 继续
    Commit //提交 如果以前UnloadOnIdle 有返回 false 的时候就会多次调用 SaveWorkflowInstanceState 和 Commit 把以前没保存的也保存了
    Complete //完成通知 持久化 引擎已经完成了一个工作流的持久化

其他没写在上面的代码都是大同小异的

转载于:https://www.cnblogs.com/wayne-ivan/archive/2007/10/09/917657.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值