嘗試.NET 4.5中狀態機工作流
NET 4.5 中狀態機工作流
結尾的總結有點與本文主題不符,是寫文章時想到的,就順手寫上了(^_^)
例子下載:
http://files.cnblogs.com/foundation/Wxwinter.Test.Statements.rar
介紹
.NET 4.5 中WF已為原WF4.0提供了狀態機模式的支持.
先看一下增加加的Activity
使用VS2011創建WorkFlow項目,選 .NET 4.5 的WF模板
在WF設計界面可以看到狀態機模板
由3個Activity組成
StateMachin 是狀態機容器
State 是狀態節點
FinalState 是結束狀態節點
在State 中具有[進入狀態],[結束狀態]兩個執行區,可以添加任意Activity,
FinalState 中具有[進入狀態]
State可以添加多條分支,在分支上可以設置[Trigger],[Condition],[Action],這些與WF4.0中其他條件類Activity設置一樣
例子
用一個例子演示一下狀態機的使用
流程業務模型
設計書簽
- publicsealedclassresultBookmark: NativeActivity
- {
- publicInArgumentbookmarkName { getset}
- protectedoverrideboolCanInduceIdle
- {
- get
- { returntrue}
- }
- protectedoverridevoidExecute(NativeActivityContextcontext)
- {
- stringbookmark = context.GetValue(bookmarkName);
- context.CreateBookmark(bookmark, newBookmarkCallback(bookmarkCallback));
- System.Console.WriteLine("創建bookmark:{0}", bookmark);
- }
- voidbookmarkCallback(NativeActivityContextcontext, Bookmarkbookmark, objectobj)
- {
- if(obj != null)
- {
- this.Result.Set(context, obj.ToString());
- }
- else
- {
- this.Result.Set(context, string.Empty);
- }
- }
- }
在設計界面用WF構建業務模型
設計State,以[A]節點為例,其他類似
#p#
設計宿主
- voidworkflowCompleted(WorkflowApplicationCompletedEventArgse)
- {
- instance = null
- System.Console.WriteLine("workflowCompleted:{0}", e.CompletionState.ToString());
- }
- voidaborted(WorkflowApplicationAbortedEventArgse)
- {
- instance = null
- System.Console.WriteLine("aborted ,Reason:{0}", e.Reason.Message);
- }
- UnhandledExceptionActionunhandledExceptionl(WorkflowApplicationUnhandledExceptionEventArgse)
- {
- System.Console.WriteLine("unhandledException:{0}", e.UnhandledException.Message);
- returnUnhandledExceptionAction.Cancel;
- }
- voidworkflowIdel(WorkflowApplicationIdleEventArgse)
- {
- System.Console.WriteLine("Idle:{0}", e.InstanceId);
- System.Console.WriteLine("--------BookmarkName---------------------------");
- foreach(varitem ine.Bookmarks)
- {
- System.Console.WriteLine("{0}", item.BookmarkName);
- }
- System.Console.WriteLine("================================");
- }
- WorkflowApplicationinstance = null
- privatevoidstartButton_Click(objectsender, EventArgse)
- {
- valueComboBox.Items.Clear();
- valueComboBox.Items.Add("A");
- valueComboBox.Items.Add("B");
- valueComboBox.Items.Add("C");
- valueComboBox.Items.Add("E");
- valueComboBox.SelectedItem = "B"
- instance = newWorkflowApplication(newmyWorkflow());
- instance.Completed = newAction(workflowCompleted);
- instance.OnUnhandledException = unhandledExceptionl;
- instance.Aborted = aborted;
- instance.Idle = workflowIdel;
- instance.Run();
- }
- privatevoidsubmitButton_Click(objectsender, EventArgse)
- {
- stringbookName =bookmarkTextBox.Text;
- stringinputValue = valueComboBox.SelectedItem.ToString();
- if(instance != null)
- {
- if(instance.GetBookmarks().Count(p => p.BookmarkName == bookName) == 1)
- {
- instance.ResumeBookmark(bookName, inputValue);
- }
- else
- {
- foreach(varv ininstance.GetBookmarks())
- {
- System.Console.WriteLine("--------請從下面選項中選擇一個BookmarkName---------------------------");
- System.Console.WriteLine("BookmarkName:{0}:,OwnerDisplayName:{1}", v.BookmarkName, v.OwnerDisplayName);
- System.Console.WriteLine("================================");
- }
- }
- }
- else
- {
- MessageBox.Show("沒有創建實例");
- }
- }
測試
總結
這本是一個應在NET 4.0 中實現的功能,其實不談數據結構與運行機制,FlowChar完全可以實現StateMachin 的所有業務邏輯.
只不過StateMachin 在VS設計器中給人一種更整潔的感覺,不過這只是展現層面的東西,之前不少人都實現過這種效果(包括我自已),理論上并不是很難,但由于WF4.0大部分的功能類從繼承Object后就開始封閉與工程級保護,在這種情況下別說繼承,就正常連引用都辦不到,當然也有辦法解決,不過實現后一般只做為概念展現,所以很多人在實際使用時采取的是自定義流程設計器,將FlowChar的結構展現成StateMachin ,通過攔截Bookmark實現[進入狀態],[結束狀態],其實這種工作量比傳統意義上開發一套業務流程平臺還有大,但為什么還有使用WF,這是很多人不理解的.其實使用WF的人基本分為兩類,一類是具備設計器開發能力的人,看到VS中的WF設計界面后就覺得WF為其提供了一套拿來就能用的業務流程平臺.這種想法是不對的,暫不分析WF是否只接適用用戶業務,就常識來說,與WCF,WPF并列的WF怎么可能是直接面對業務用戶的.另一類選擇WF的人是看中了WF對狀態的副本處理,事物處理,補償處理這些從COM+延續下來的理念.很多時候我一直認為WCF +WF就是一個新版本的COM+
最后不得不提一下,雖然WF實現了FlowChar與StateMachin ,但其數據結構并不是圖,而是樹.如果既對Expression Tree熟悉,又對WF熟悉,你會發現Expression Tree就是一個WF數據結構精簡版.談到Expression Tree了解的人是多了,我也好解釋了,這種數結構其實與內存中的棧管理方式很象,這就決定了調用只能指向棧開始,而不能任意指向棧的任意位置(不談溢出,GOTO指針這個層面的問題).
為什么提上面這段內容,是因為我要說明由于這種數據結構我們很難現以下功能(這是一個業務功能,我先用C#風格有代碼描述一下):
上面這段代碼看起來有些瘋狂,我們不從代碼層面考慮(不加條件判斷,不提動態編譯,ICO,AOP),我只想這樣寫,我希望當程序運行到[24]時自動告訴我缺少哪個上下文(如obj),并讓我補齊上下文后繼續執行.
將這個問題業務化:
上車前要買票,(買票是上車的前置條件)
但我已經上了車卻沒買票,是補票還是將我趕下車買完票再上車.這就是經典的[補償處理]機制
程序員說:"你們的業務總變,你們都說不清,讓我們怎么開發"
客戶說:"我們要是業務從來不變,每個人都能說清,要你們開發系統做什么"
數學是嚴謹的,而真實的業務到處充滿了變通.如何用嚴謹的數學來構建變通業務的邏輯模型才是從事企業應用開發程序員所面臨的問題
原文鏈接:http://www.cnblogs.com/foundation/archive/2011/09/19/2181324.html
【編輯推薦】
- 調用ASP.NET工作流:承載及限制
- ASP.NET工作流的創建與啟動
- ASP.NET數據庫連接類ClassConn以及oledb數據庫連接方法
- ASP.NET數據庫驅動類的實現:DBHelper
- 用C#寫的ASP.NET數據庫操作類