工作流-----WorkFlow


我們都知道對於一個OA系統來說,最重要的也是不可或缺的一個重要環節那就是對於工作流的實現,為此,最近專門在學習如何使用WorkFlow,問前輩,前輩也說道K2工作流引擎挺不錯,自己同時也翻閱了一些資料,但因為自己這個OA項目主要是采用微軟的ASP.NET MVC 來開發的,所以還是決定使用微軟的那一套WorkFlow工作流引擎。不得不說,微軟在對於客戶體驗這方面做的還真是不錯的。為了方面學習,我也是通過一個小案例來學習WorkFlow,在這里也拿出來和大家共同分享學習。

小案例(請假工作流)

說明:

1.程序集:system.Activities

2.Xaml文件:工作流文件設計的類型,最終會被處理為一個類

3.狀態機工作流(開發中使用的類型)

首先:創建一個Windows窗體應用程序,命名WorkFlowDemo

注意:為了便於工作流的展示,把當前項目的屬性-----》服務,把輸入類型由Windows應用程序改為控制台應用程序

接下來,簡單點設計一下窗體頁面

設計一下流程圖:(狀態機控件在工具箱)對於其中的工具使用,可以自己簡單學習,很容易上手

前期工作完成接下來就是代碼實現的時候了,為窗體的單擊按鈕注冊事件

 1 using System;
 2 using System.Collections.Generic;
 3 using System.ComponentModel;
 4 using System.Data;
 5 using System.Drawing;
 6 using System.Linq;
 7 using System.Text;
 8 using System.Threading.Tasks;
 9 using System.Windows.Forms;
10 using System.Activities;
11 
12 namespace WindowsFormsApplication1
13 {
14     public partial class Form1 : Form
15     {
16         public Form1()
17         {
18             InitializeComponent();
19         }
20 
21        //創建一個工作流對象
22         WorkflowApplication wfapp;
23         private void btnsave_Click(object sender, EventArgs e)
24         {
25 
26             //1.准備好工作流中需要的參數
27             Dictionary<string, object> dict = new Dictionary<string, object>();//用來向工作流傳遞參數
28             dict.Add("LeaveDays", int.Parse(txtDays.Text));
29 
30             //2.創建一個工作流應用對象
31             wfapp = new WorkflowApplication(new LeaveActivity(), dict);
32 
33       
34             //3.調用wfapp對象的Run方法
35             wfapp.Run();
36         }
37 
38        private void btnjinli_Click(object sender, EventArgs e)
39         {
40             bool result = radioButton1.Checked;
41 
42            //喚醒書簽
43             wp.ResumeBookmark("經理審批", result);
44         }
45 
46         private void button2_Click(object sender, EventArgs e)
47         {
48             bool result = radioButton3.Checked;
49             wp.ResumeBookmark("財務總監審批", result);
50         }
51     }
52 }
View Code

這時,產生了工作流中一個重要的內容------書簽(BookMark)

場景:在實際業務場景中,流程一般都是復雜的,不會一口氣從開始走到最后,當在某一個需要暫停的時候,這時,書簽很好的充當了這個使者,就好像我們平時看書,看到某一頁突然有事要離開,但辦完事回來還是要接着看的對不對,通常我們會在暫停的位置放置一個標簽,等我們下次繼續翻閱,可以很快的知道上一次暫停的位置。

步驟:

1.在項目中添加一個代碼活動(CodeActivity),

【注意】

  1. 將繼承的CodeActivity父類改成NativeActivity,
  2. 同時將Execute方法中的參數也要修改為NatveActivityContext
  3. 重寫父類的CanIncludeIdIe屬性

2.在該代碼活動的Execute方法里創建書簽

代碼實現:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;

namespace WindowsFormsApplication1
{

    public sealed class WaitProcess :NativeActivity
    {
        //輸出型參數
        public OutArgument<bool> Result { get; set; }
        //輸入型參數
        public InArgument<string> BookMarkName { get; set; }
        //重寫父類的CanIncludeIdIe屬性
        protected override bool CanInduceIdle
        {
            get
            {
                return true;
            }
        }

        protected override void Execute(NativeActivityContext context)
        {
            //創建書簽
            context.CreateBookmark(context.GetValue(BookMarkName), FunCallBack);
        }

        private void FunCallBack(NativeActivityContext context, Bookmark bookmark, object value)
        {

            Console.WriteLine("工作流被喚醒");
         
            context.SetValue(Result,Convert.ToBoolean(value));
        }


    }
}
View Code

操作結果:

點擊提交申請

點擊第一個審批(因為我在流程圖那邊設置了當天數<6時,經理審批同意后直接結束)

別急,做到這里,也只是完成了三分之一,因為你會發現當你點擊提交申請,這時,關閉整個應用程序,當你下次訪問,點擊審批的時候,會報錯,

這是為什么呢?因為你點擊提交申請后退出,這時整個WorkFlowApplication對象也會被銷毀,那么問題來了,如何做到工作流實例的具體化?

方案有很多種,你可以采用xml文件保存,也可以把它保存到數據庫,而我將采取后面那種方式,那么你又會說了,數據庫我該怎么設計,別擔心,微軟已經幫我們寫好了SQL腳本,你只需要找到它們並執行一下就好了。

步驟:

步驟:

  1. 建立數據表

在C:\Windows\Microsoft.NET\Framework\v4.0.30319\SQL\en中可以找到兩個微軟寫好的數據庫腳本

 

然后數據庫中先執行后者腳本,在執行前者腳本

將工作流對象往數據庫中存儲

引入命名空間:

using System.Activities.DurableInstancing;

using System.Runtime.DurableInstancing;

  1. 什么時候持久化工作流對象?

在工作流創建之后,為工作流對象注冊一個事件:

wfapp.PersistableIdle += a => { return PersistableIdleAction.Unload; };

  1. 創建一個SqlWorkFlowInstanceStore對象

SqlWorkflowInstanceStore ss = new SqlWorkflowInstanceStore("server=.;daabase=WorkFlow;uid=sa;pwd=123;");

關聯持久化的工作流對象和具體的存儲實例

wfapp.InstanceStore = ss;

 

  1. 如何從數據庫中加載未完成的工作流實例

創建一個存儲實例對象和一個工作流對象,並將它們進行關聯,

注意:重新new的WorkFlowApplication對象也要重新注冊wfapp.PersistableIdle += a => { return PersistableIdleAction.Unload; };這個事件

最后調用WorkFlowApplication對象的Load(Guid guid)方法

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Activities;
using System.Activities.DurableInstancing;
using System.Runtime.DurableInstancing;

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        WorkflowApplication wfapp;
        private void btnsave_Click(object sender, EventArgs e)
        {
  

            //1.准備好工作流中需要的參數
            Dictionary<string, object> dict = new Dictionary<string, object>();//用來向工作流傳遞參數
            dict.Add("LeaveDays", int.Parse(txtDays.Text));
            //2.創建一個工作流應用對象
            wfapp = new WorkflowApplication(new LeaveActivity(), dict);

            //在工作流創建之后,為工作流對象注冊一個事件
            wfapp.PersistableIdle += a => { return PersistableIdleAction.Unload; };

            //關聯持久化的工作流對象和具體的存儲實例
            SqlWorkflowInstanceStore ss = new SqlWorkflowInstanceStore("server=.;daabase=WorkFlow;uid=sa;pwd=123;");
            wfapp.InstanceStore = ss;
            //3.調用wfapp的Run方法
            wfapp.Run();
        }

        private void button1_Click(object sender, EventArgs e)
        {
           

            //從數據中加載實例
            SqlWorkflowInstanceStore ss = new SqlWorkflowInstanceStore("server=.;daabase=WorkFlow;uid=sa;pwd=123;");
            wfapp = new WorkflowApplication(new LeaveActivity());
            wfapp.PersistableIdle += a => { return PersistableIdleAction.Unload; };
            wfapp.InstanceStore = ss;
            //wfapp.Load("CA15C81C-FE95-4B0B-B1F4-B5F1478BEF3C");//傳入的是一個guid參數
            bool result = radioButton1.Checked;
            //喚醒書簽
            wfapp.ResumeBookmark("經理審批", result);
        }
    }
}
View Code

效果圖:

你會發現在你的數據庫表中多了一條記錄,這時記錄了你上一次未完成的操作(把這個Guid復制下來,放到按鈕1審批的代碼中Load方法中)因為是做測試用

 

第二次在運行,直接點擊經理審批對應的審批按鈕,你會發現:

同時數據庫中的記錄也不見了

 

好了,具體實現就這么多了,但是還存在一個問題,那就是對於某個按鈕事件,你會發現重復性的代碼太多了,不妨就自己去進行封裝吧!做成一個屬於自己的Helper!

最后,非常希望大家可以提出批評和建議。謝謝!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM