自從做了程序員,發現自己長胖了,而且自己的身體抵抗力也出了問題,最近身體不適,公司工作任務最近也很趕,上次寫了WF4.0的簡介,這次就工作中工作流設計的幾種方式稍微總結一下。設計工作流包括四種方式:流程圖工作流,程序工作流,狀態機工作流,自定義命令性代碼創建工作流.
流程圖工作流
工作流設計中最常用的就是FlowChart,FlowChart用於實現非順序的工作流,如果不適用FlowDecision節點,FlowChart也可以用於順序工作流。首先來看下工具箱提供的流程圖節點:
Flowchart 活動是包含從 FlowNode 繼承的流節點集合的活動,流節點可以包含要執行以及將執行指向其他流節點的子活動。構建流程圖的過程中,可以使用三種元素類型來進行流控制:
FlowStep:在流程圖中構建一個執行步驟的模型;
FlowDecision:類似於if的語法,傳入條件可以進行判斷;
FlowSwitch:類似於Switch,可以根據傳入條件判斷;
關於FlowDecison建一個簡單的流程,從流程圖中拖一個FlowDecision,判斷條件為:10==100
這個時候我們可以查看一下后台生成的代碼如下(FlowSwitch類似就不舉例):
程序工作流
程序工作流使用的流控制方法與程序語言中使用的流控制方法類似。這些構造包括 While,DoWhile,If....。使用 FlowChart和 Sequence等其他流控制活動,可以隨意組合這些工作流。
這個就是需要根據具體的業務使用,就不一一舉例~
狀態機工作流
.NET Framework 4沒有提供狀態機活動或工作流模型,NET Framework 4.5中為WF4.0提供了狀態機支持,這里有 個老外寫的例子,大家可以自己研究一下:
http://blogs.msdn.com/b/morgan/archive/2010/06/15/a-practical-state-machine-example.aspx
自定義命令性工作流
首先看一個最簡單WriteLine的輸出:
Activity activity = new WriteLine() { Text = "keso" }; WorkflowInvoker.Invoke(activity);
輸出一個Sequence:
Activity activity1 = new WriteLine() { Text = "keso" }; Activity activity2 = new WriteLine { Text = "FlyElephant" }; Activity sequence = new Sequence() { Activities = { activity1, activity2 } }; WorkflowInvoker.Invoke(sequence);
特別說明:WorkflowInvoker提供調用工作流的簡單方法,就像方法調用一樣,並且只可用於不使用持久性的工作流。WorkflowApplication 為執行工作流提供更豐富的模型,包括生命周期事件通知、執行控制、書簽恢復和持久性。這里就簡單的用WorkflowInvoker將就一下.
如果你對上面的代碼不是很爽,你可以這樣寫:
WriteLine line1= new WriteLine() ; line1.Text = "keso"; WriteLine line2 = new WriteLine(); line2.Text = "FlyElephant"; Sequence sequence = new Sequence(); sequence.Activities.Add(line1); sequence.Activities.Add(line2); WorkflowInvoker.Invoke(sequence);
下面開始看一個簡單的小例子,輸出一個隨機數到控制台:
//定義變量number Variable<int> number = new Variable<int> { Name = "Test" }; Activity activity = new Sequence { Variables = { number }, Activities = { //將隨機數的數值賦值給number new Assign<int>(){ To=number, Value=new Random().Next(1,100) }, new WriteLine(){ //取值 Text = new InArgument<string>((context) => "隨機數:" + number.Get(context)) } } }; WorkflowInvoker.Invoke(activity);
關於取值那一塊需要說明一下的就是去取值需要傳入的值是AcitivityContext,使用Lambda表達式進行訪問,Lambda不可序列化成XAML格式,這個時候需要換種寫法:
Text = new InArgument<string>((context) => "隨機數:" + number.Get(context))
動態活動
上面通過活動的組合,設置活動的參數和屬性可以是實現代碼編寫工作流定義,但是唯一的缺憾就是可以綁定現有參數卻沒法將新的參數添加到活動中,定義的參數在保存為內存對象樹的時候是有對應的CLR類型,如果新的參數則沒法解析,這個時候可以考慮使用DynamicActivity。
簡單實現兩個整數的乘法:
//定義兩個參數 InArgument<int> number1 = new InArgument<int>(); InArgument<int> number2 = new InArgument<int>(); DynamicActivity<int> wf = new DynamicActivity<int> { Properties = { //新建屬性 new DynamicActivityProperty{ Name="First", Type=typeof(InArgument<int>), Value=number1 }, new DynamicActivityProperty{ Name="Second", Type=typeof(InArgument<int>), Value=number2 } }, Implementation = () => new Sequence() { Activities = { new Assign<int>{ To=new ArgumentReference<int>{ArgumentName="Result"}, // 取值 Value=new InArgument<int>((context)=>number1.Get(context)*number2.Get(context)) } } } }; Dictionary<string, object> wfParams = new Dictionary<string, object>{ { "First", 36 }, { "Second", 72 } }; //先給屬性賦值,然后獲取乘積 int result = WorkflowInvoker.Invoke(wf, wfParams); Console.WriteLine(result);
第二篇先寫到這里吧,有些東西還是需要有點基礎的,一個個的寫實在感覺太龐雜,如果周末有空補幾篇稍微基礎一點的使用,你的推薦就是我寫作的最大動力,如果你覺得有所收獲,順手給個贊吧,多謝~