• 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

  • 相关阅读:
    bzoj2243: [SDOI2011]染色
    bzoj4538: [Hnoi2016]网络
    bzoj 1004
    数论小结2.
    数论小结1.
    Catalan Number
    uva 11645
    uva 01510
    redis cluster介绍
    搭建redis-sentinel(哨兵机制)集群
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/1399381.html
Copyright © 2020-2023  润新知