asp.net中的报销多级审批工作流 (状态机版本)

      上篇asp.net中的报销多级审批工作流 ,提到参考了网上一个具体的项目,项目中用状态机工作流完成,基于学习的原因,我采用顺序工作流,事件驱动方式实现了同样的功能。后来学习到了状态机,觉的状态机实现也特别方便。 下面我分享下状态机工作流中几个主要的活动。

      顺序工作流与状态机工作流的区别:

          顺序工作流是一种可以预测,流程比较固定,而状态机工作流不可预测,主要靠外部事件驱动来实现,对外的交互比较多,系统的状态需要外部事件的触发来改变。

      状态机工作流活动图:

 

      1:State Activity,在状态机工作流中代表了一个具体的状态,这种状态机以事件驱动为主,和之前顺序工作流中的事件驱动有点类似。在整个状态机工作流中,会有一个初始化的State Activity和一个表示完成的State Activity,我们从工具箱中拉一个State Activity,然后单击右键,出现如下图,绿色的表示初始化State Activity,而红色的表示完成的State Activity,分别会在State Activity的左上角有相应的标示。

 


      2:EventDriven Activity,做为State Activity的子活动,状态中的所有事件都存放在这。

      3:HandleExternalEvent activity,这就是具体的外部事件活动,它即可以用在顺序工作流中,也可以用在状态机工作流中。设置方法可参考上篇文章asp.net中的报销多级审批工作流

      4:SetState Activity,外部事件的执行会使状态机工作流中的状态发生变化,说的通俗点就是告诉状态机下一步的动向。我们只要设置它的一个关键属性就行:TargetStateName,这个属性是指向状态机中一个已经存在的具体状态。设置好后就会发生在设计器中出现连接箭头。

       宿主调用代码的封装:

          我发现源项目中没有封装对于WorkflowRuntime和WorkflowInstance的使用,每个审批页面都会出现很多初始化工作流引擎, 创建工作流实例的代码,这里我在公共层中封装了一个WorkflowWrapper类。主要方法有:

         1:InitWorkFlowRuntime,初始化工作流引擎。

         2:StartWorkFlowRuntime,启动工作流引擎。

         3:OnWorkflowIdled,工作流闲置事件。

        4:CreateWorkFlowInstance,创建一个工作流实例。

        5:GetWorkflowInstance,返回一个工作流实例。

        6:StartWorkFlowInstance,启动工作流实例。

        7:GetGetWorkflowById,加载一个已经存在的未完成的工作流实例。

        8:Dispose,释放资源。

      WorkflowWrapper类详细代码如下:

 
public    class  WorkflowWrapper:IDisposable
    {
        
static  WorkflowRuntime runtime; // 运行时
         static   WorkflowInstance instance; // 实例
         static  ExternalDataExchangeService service; // 外部数据交换服务
         static  WorkflowPersistenceService perService; // 持久化服务
         public   static   BLL_Approve project; // 实现接口类
        ///   <summary>
       
///  启动工作流引擎
       
///   </summary>
         public   void  StartWorkFlowRuntime()
        {
            
if  (runtime  !=   null )
            {
                
try
                {
                    
// 启动工作流引擎
                    runtime.StartRuntime();
                }
                
catch (Exception ex)
                {
                    
this .InitWorkFlowRuntime();
                }
            }
            
else
            {
                
this .InitWorkFlowRuntime();
            }
        }
       
///   <summary>
       
///  初始化工作流引擎
       
///   </summary>
         public   void  InitWorkFlowRuntime()
        {         
            runtime 
=   new  WorkflowRuntime();
            service 
=   new  ExternalDataExchangeService();
            project 
=   new  BLL_Approve();

            perService = new SqlWorkflowPersistenceService(ConfigurationManager.

            ConnectionStrings["perstr"].ConnectionString);

            if  (runtime.GetService(service.GetType())  ==   null ) // 服务不能重复加入
            {
                runtime.AddService(service);
            }
            
if  (runtime.GetService(perService.GetType())  ==   null )
            {
                
// 加入持久化服务
                runtime.AddService(perService);
            }
            
if  (service.GetService(project.GetType())  ==   null )
            {
                
// 将此类加入外部数据交换服务
                service.AddService(project);
            }
            
// 工作流闲置事件
            runtime.WorkflowIdled  +=  OnWorkflowIdled;
            
// 启动工作流引擎
            runtime.StartRuntime();
        }
       
///   <summary>
       
///  工作流闲置事件
       
///   </summary>
       
///   <param name="sender"></param>
       
///   <param name="e"></param>
         private    void  OnWorkflowIdled( object  sender, WorkflowEventArgs e)
        {
            e.WorkflowInstance.TryUnload();
// 将内存数据持久化到数据库中
        }
       
///   <summary>
       
///  创建一个工作流实例
       
///   </summary>
         public   void  CreateWorkFlowInstance()
        {
            
// 确保启动了工作流引擎
             this .StartWorkFlowRuntime();
            
// 创建一个工作流实例

            string sWorkFlowType = 

            ConfigurationManager.AppSettings["WorkFlowType"].Trim();

            switch  (sWorkFlowType)
            {
                
case   " 1 " :

                    instance = runtime.CreateWorkflow(typeof(

                    ApproveWorkFlow.MyWorkFlow.Workflow1));

                    break ;
                
case   " 2 " :

                    instance = runtime.CreateWorkflow(typeof(

                    ApproveWorkFlow.MyWorkFlowStateMachine .Workflow1));

                    break ;
            }         
        }
       
///   <summary>
       
///  返回一个工作流实例
       
///   </summary>
       
///   <returns></returns>
         public  WorkflowInstance GetWorkflowInstance()
        {
            
if  (instance  ==   null )
            {
                
this .CreateWorkFlowInstance();
            }          
            
return  instance;          
        }
       
///   <summary>
       
///  启动工作流实例
       
///   </summary>
         public   void  StartWorkFlowInstance()
        {
            
this .CreateWorkFlowInstance();
            instance.Start();
        }
       
///   <summary>
       
///  加载一个已经存在的未完成的工作流实例
       
///   </summary>
       
///   <param name="_Guid"></param>
         public  WorkflowInstance  GetGetWorkflowById(Guid _Guid)
        {
            
// 确保启动了工作流引擎
             this .StartWorkFlowRuntime();
            
return   runtime.GetWorkflow(_Guid);
        }
       
///   <summary>
       
///  释放资源
       
///   </summary>
         public   void  Dispose()
        {
            
if  (runtime  !=   null )
            {
                
// 停止工作流引擎
                runtime.StopRuntime();
                
// 释放占用的资源
                runtime.Dispose();
            }                     
        }     
    }

         小结:无论是之前的顺序工作流还是现在的状态机工作流,都是事件驱动性工作流,外部调用上没有任何区别,唯一的区别就在创建工作流实例,我们看下上面的创建工作流实例的方法,为了演示方便,我在web.config文件中加了一个配置节,用来控制创建的工作流类型:

<!-- 工作流类型  1 :顺序工作流  2 :状态机工作流 -->
    
< add key  = " WorkFlowType "  value  = " 2 " />

        经过这样的封装后我们来看下页面层的代码:页面中只会出现业务逻辑层的类,WorkFlow相关的类尽量不要直接出现,代码的复用也得到了提高,第二部分为提交事件的代码:

      BllExpense Bll;
        
static   WorkflowWrapper _WorkflowWrapper  =   new  WorkflowWrapper();
        
protected   void  Page_Load( object  sender, EventArgs e)
        {           
            Bll 
=   new  BllExpense();
            
if  ( ! IsPostBack)
            {
                ViewState[
" userName " =  Request[ " name " ];
                
this .tbName.Text  =  ViewState[ " userName " ].ToString();
                BindData(ViewState[
" userName " ].ToString());               
            }
            
// 初始化,启动工作流引擎
            _WorkflowWrapper.StartWorkFlowRuntime();

        }

 

           用户的提交事件代码:

  Guid workflowId  =   new  Guid( this .tbNo.Text);
                
// 读取一个未完成的工作流实例

                WorkflowInstance _WorkflowInstance= 

              _WorkflowWrapper.GetGetWorkflowById(workflowId);

 

                ExpenseAccountInfo info = new ExpenseAccountInfo(                             workflowId, Convert.ToDecimal(this.tbMoney.Text), 

this.tbName.Text, DateTime.Now.ToShortDateString(), 

"结束"this.tbNotes.Text);

                // 触发工作流事件

                WorkflowWrapper.project.RaiseStaffDelete(info);

 

               //从数据库中查找作流,并加入内存中(持久化的作用)

                _WorkflowInstance.TryUnload();
                
// 释放资源
                _WorkflowWrapper.Dispose();

          

注:

    原项目地址:http://download.csdn.net/down/948601/oxch2008

转载于:https://www.cnblogs.com/ASPNET2008/archive/2009/02/27/1399381.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值