• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
flashelf
博客园    首页    新随笔    联系   管理    订阅  订阅

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

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

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

接上篇文章 “状态机工作流.实列.报销审批流程(二) ”
     本文主要讲述,如何实现一个自定义的,状态保存服务,原本是要写一个保存到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 //完成通知 持久化 引擎已经完成了一个工作流的持久化

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

posted @ 2006-10-07 18:43  曲滨*銘龘鶽  阅读(3385)  评论(6)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3