作為即將推出的 Microsoft .NET Framework 3.0 的重要組成部分,Windows Workflow Foundation 提供了編程模型和運(yùn)行時(shí)引擎,以便基于安裝了 .NET Framework 2.0 或更高版本的 Window 平臺(tái)來構(gòu)建支持工作流的應(yīng)用程序,其最低運(yùn)行要求為 Windows xp Service Pack 2 (SP2) 或 Windows Server 2003。
從軟件的角度看,需要人為操作的多數(shù)是異步事件處理、狀態(tài)保持以及共享服務(wù)器可用性。Windows Workflow Foundation 實(shí)際上支持任何涉及人為操作的情況。
每一個(gè)工作流都是一個(gè)聲明程序,其中,每條程序語句都用稱為活動(dòng)的組件表示。關(guān)于 Windows Workflow Foundation 的最大誤區(qū)之一在于將所有要素活動(dòng)都看成是順序相連或按狀態(tài)機(jī)轉(zhuǎn)換相連。實(shí)際上,Windows Workflow Foundation 對(duì)執(zhí)行模型進(jìn)行了活動(dòng)自動(dòng)控制方面的虛擬化。這使您能編寫可以捕捉各種控制流模式的復(fù)合活動(dòng),范圍包括多種連接和合并、狀態(tài)機(jī)、圖形、序列、交叉存取和非本地退出等。總之,它將使您能夠通過“高保真”的復(fù)合活動(dòng)對(duì)存在于現(xiàn)實(shí)世界中的控制流模式進(jìn)行建模。然而,Windows Workflow Foundation 提供了針對(duì)以下兩種模式的內(nèi)置活動(dòng):順序工作流和狀態(tài)機(jī)工作流。
正如我所談到的,工作流的構(gòu)造塊就是活動(dòng)。構(gòu)造這樣一個(gè)工作流意味著將活動(dòng)進(jìn)行組合以創(chuàng)建所需的模型來解決碰到的問題。雖然 Windows Workflow Foundation 提供了很多內(nèi)置的活動(dòng),但依然可以通過自定義活動(dòng)對(duì)其進(jìn)行完全擴(kuò)展。了解“開箱即用”活動(dòng)的目標(biāo)和功能對(duì)于充分理解該平臺(tái)的真實(shí)潛能十分要害。本期專欄將帶您瀏覽安裝 Windows Workflow Foundation Runtime 和 Visual Studio 2005 Designer 時(shí)涉及的標(biāo)準(zhǔn)工作流活動(dòng)。
“開箱即用”活動(dòng)
Windows Workflow Foundation 是 .NET Framework 3.0 (原先稱為 WinFX?)的組成部分。雖然它只是一個(gè)測(cè)試版本,但我發(fā)現(xiàn)最新的 Community Technology PReview(社區(qū)技術(shù)預(yù)覽,CTP)版非常穩(wěn)定,許多公司正廣泛使用該版本開發(fā)應(yīng)用程序。因此,已經(jīng)出現(xiàn)大量工具和自定義活動(dòng),一個(gè)基于新聞組和論壇(如 wf.netfx3.com)的有效的技術(shù)支持社區(qū)正日益發(fā)展壯大。假如您對(duì)工作流應(yīng)用程序感愛好,那么越早熟悉它越好。
若要查找最新的下載,請(qǐng)?jiān)L問 Windows Workflow Foundation。安裝完畢后,啟動(dòng) Visual Studio 2005,打開一個(gè) Visual Basic? 或 C# 工作流項(xiàng)目,查看工具箱中的內(nèi)容。根據(jù)您所選擇的項(xiàng)目類型,工具箱可能如圖 1 中所示的一種。
圖1 工具箱里的工作流活動(dòng)(Click the image for a smaller view) 圖2
控制流活動(dòng)治理圖形活動(dòng)執(zhí)行的順序。列表列出了實(shí)現(xiàn)循環(huán)的條件塊以及構(gòu)造。執(zhí)行活動(dòng)包括多種構(gòu)造,這些構(gòu)造可終止或掛起工作流、引發(fā)異常、執(zhí)行內(nèi)部或外部代碼,或者生成另一個(gè)工作流。多數(shù)工作流需要與主機(jī)環(huán)境同步 — 通常是 Windows Forms 應(yīng)用程序或 asp.net 應(yīng)用程序。事件組中的活動(dòng)能使工作流停止以等待外部事件、處理接收的事件,或只是在執(zhí)行下一步之前進(jìn)行等待。最后,Web 服務(wù)和狀態(tài)組將目標(biāo)鎖定在工作流的兩種非凡功能 — 將內(nèi)部引擎為公開為 Web 服務(wù)或公開為狀態(tài)機(jī)。讓我們檢查一下框架中的主要活動(dòng),然后分組進(jìn)行。通過條件控制工作流
假如在工作流中指定了條件,運(yùn)行時(shí)引擎將對(duì)條件進(jìn)行計(jì)算,然后根據(jù)計(jì)算結(jié)果進(jìn)行操作。兩種基于條件的核心活動(dòng)是 IfElse 和 Policy。IfElse 活動(dòng)的執(zhí)行方式如同高級(jí)編程語言中的一條典型的 If 語句。它可以包含任意多基于條件的分支,以及一個(gè)在其他條件不滿足情況下執(zhí)行的默認(rèn)分支。而 Policy 活動(dòng)表示一系列規(guī)則。在 Windows Workflow Foundation 中,一條規(guī)則包括一個(gè)條件以及一個(gè)或一個(gè)以上引發(fā)的操作。可以將規(guī)則看作 If-Then-Else 語句,其中條件對(duì)應(yīng) If 塊的 Boolean 臨界條件,操作定義了 Then 和 Else 子句。讓我們進(jìn)一步了解各個(gè)活動(dòng),然后對(duì)它們進(jìn)行比較。
Public Property MinimumLength() As Integer Get Return _minLength End Get Set(ByVal value As Integer) _minLength = value End Set End Property
圖 4 針對(duì) IfElse 活動(dòng)的 Condition Editor(Click the image for a larger view)
當(dāng)您試圖讀取 MinimumLength 的值時(shí),運(yùn)行時(shí)會(huì)結(jié)束調(diào)用屬性的 get 存取器。該存取器能夠回復(fù)私有成員 _minLength 的值。IfElse 活動(dòng)中的最后分支可以沒有條件。在這種情況下,它將作為 IF 工作流語句的 Else 分支。
指定條件的第二種方法是通過臨時(shí)代碼。在這種情況下,您可以為工作流類添加方法,例如:
Sub EvalCondition(ByVal sender As Object, ByVal e As ConditionalEventArgs) e.Result = ... ' Boolean value End Sub 該函數(shù)必須與接受對(duì)象和 ConditionalEventArgs 類并回復(fù) void 的簽名相匹配。ConditionalEventArgs 類的 Result 成員將設(shè)置為布爾值,代表?xiàng)l件的計(jì)算結(jié)果。
當(dāng)您真正需要控制工作流的流動(dòng)并連接各種工作塊時(shí),您應(yīng)該使用 IfElse 活動(dòng)組合。假如您所需要的僅僅是一個(gè)編程 If 語句序列,帶有附加到分支的簡(jiǎn)單代碼,那么最好使用 Policy 活動(dòng)。Policy 活動(dòng)是一個(gè)規(guī)則集合。與各規(guī)則相關(guān)的代碼僅限于設(shè)置工作流屬性,調(diào)用工作流方法或針對(duì)引用的程序集中的類型的靜態(tài)方法。
活動(dòng)與已排序的規(guī)則集合相關(guān)聯(lián),您可以通過編輯器定義規(guī)則。每條規(guī)則都有優(yōu)先級(jí)和 Active 屬性。這兩種屬性的組合確定了是否應(yīng)當(dāng)評(píng)估規(guī)則,以及采用哪種優(yōu)先級(jí)。另外,規(guī)則還必須指定重估行為 —“Always(始終)”(默認(rèn)值)或“Never(從不)”。假如設(shè)置為“Always”,規(guī)則將根據(jù)需要進(jìn)行重估,否則只進(jìn)行首次評(píng)估,以后無論工作流狀態(tài)如何變化,也不再更改。
IF this.MinimumLength <= 8 THEN RefreshInternalState() 有誰能夠知道 RefreshInternalState 方法將要做什么?該方法可能會(huì)觸及涉及策略活動(dòng)中其他規(guī)則的工作流屬性。通過使用方法聲明中的屬性,您可以顯式地表示該方法的行為:
<RuleWrite("PassWordLevel")> _ Public Sub RefreshInternalState() Me.PasswordLevel = 1 End Sub RuleWrite 屬性表示方法將要修改指定的屬性;同樣,RuleRead 屬性表示方法將要從指定的屬性中進(jìn)行讀取。這樣,就可以為運(yùn)行時(shí)引擎提供明確清楚的信息以確保規(guī)則設(shè)置同步。
最后,您可以編寫顯式調(diào)用對(duì)涉及的屬性進(jìn)行更新的操作。例如:
IF this.MinimumLength <= 8 THEN RefreshInternalState() Update("PasswordLevel") 規(guī)則操作中的 Update 方法會(huì)計(jì)劃對(duì)包含指定屬性的所有規(guī)則進(jìn)行重估。 QQRead.com 推出數(shù)據(jù)恢復(fù)指南教程 數(shù)據(jù)恢復(fù)指南教程 數(shù)據(jù)恢復(fù)故障解析 常用數(shù)據(jù)恢復(fù)方案 硬盤數(shù)據(jù)恢復(fù)教程 數(shù)據(jù)保護(hù)方法 數(shù)據(jù)恢復(fù)軟件 專業(yè)數(shù)據(jù)恢復(fù)服務(wù)指南 循環(huán)和重復(fù)活動(dòng)
這組活動(dòng)提供了典型的 While 活動(dòng)以及 Replicator 活動(dòng),這些活動(dòng)與典型的 For 循環(huán)有些共同點(diǎn)。While 活動(dòng)接受條件并在每次迭代開始時(shí)對(duì)該條件進(jìn)行計(jì)算。假如條件為“true”,該活動(dòng)將運(yùn)行指定的子活動(dòng)并重復(fù)直至條件為“false”。請(qǐng)注重在 While 主體內(nèi)答應(yīng)進(jìn)行單一活動(dòng)。因此,您可能要使用一個(gè)復(fù)合活動(dòng)(如 Sequence 或 Parallel)在循環(huán)中執(zhí)行多個(gè)活動(dòng)。(在此處,使用術(shù)語“交錯(cuò)”可能比“并行”更加準(zhǔn)確。因?yàn)闆]有涉及 Parallel 活動(dòng)的并發(fā),只有同一線程內(nèi)的交錯(cuò)。) 與 Foreach 語句類似,Replicator 活動(dòng)創(chuàng)建并執(zhí)行指定的子活動(dòng)的給定數(shù)量的實(shí)例。您可以只指定一個(gè)子活動(dòng),但答應(yīng)使用復(fù)合或自定義活動(dòng)。您不能通過聲明性屬性來控制迭代數(shù)。但是,您可以為初始化事件編寫一個(gè)處理程序,并針對(duì)各個(gè)需要的實(shí)例,使用初始化數(shù)據(jù)填充 CurrentChildData 集合:
Sub replicator1_Initialized(ByVal sender As Object, ByVal e As EventArgs) Console.WriteLine("Initializing ...") replicator1.CurrentChildData.Add("You are #1") replicator1.CurrentChildData.Add("You are #2") replicator1.CurrentChildData.Add("You are #3") End Sub 前面所述的代碼段規(guī)定了 Replicator 的子活動(dòng)的三個(gè)實(shí)例的順序,每個(gè)實(shí)例均使用給定的字符串進(jìn)行初始化。請(qǐng)注重,假如您將 CurrentChildData 集合置為空,Replicator 將不運(yùn)行任何子活動(dòng),并僅限于觸發(fā)頂級(jí)事件,如 Initialized 事件和 Completed 事件。您可以使用對(duì)象(不一定是字符串)初始化子活動(dòng),包括自定義類的實(shí)例。Replicator 還包括標(biāo)示各個(gè)子活動(dòng)初始化和完成的事件。默認(rèn)情況下,子實(shí)例按順序運(yùn)行,盡管通過設(shè)置 ExecutionType 屬性,您可以選擇并行執(zhí)行。假如需要并行執(zhí)行,在復(fù)制器開始并執(zhí)行并行線程前,可以創(chuàng)建所有子活動(dòng)實(shí)例。當(dāng)以順序模式執(zhí)行時(shí),只有當(dāng)前一個(gè)活動(dòng)結(jié)束時(shí)下一個(gè)活動(dòng)才能被實(shí)例化。 假如沒有通過 UntilCondition 屬性設(shè)置全局條件,Replicator 將在所有復(fù)制完成后才結(jié)束,否則,將在 UntilCondition 為“true”時(shí)終止活動(dòng)。值得注重的是,盡管在所有子活動(dòng)已完成并且 UntilCondition 屬性計(jì)算為“false”時(shí)活動(dòng)將被掛起,Replicator 也從不通過類似 While 循環(huán)中的子活動(dòng)進(jìn)行循環(huán)。在對(duì)活動(dòng)進(jìn)行全局實(shí)例化后,在每個(gè)子活動(dòng)完成后以及所有包括的活動(dòng)都已完成后,將對(duì) UntilCondition 進(jìn)行計(jì)算。但是有時(shí),假如條件計(jì)算為“true”,Replicator 將立即退出。
您可以將 ConditionedActivityGroup (CAG) 活動(dòng)中的條件執(zhí)行和循環(huán)混合在一起。CAG 包含一些子活動(dòng)(可能是復(fù)合活動(dòng)),并可運(yùn)行這些活動(dòng),直至滿足全局條件。基本上,CAG 組合了 While 和 IfElse 活動(dòng)的行為。通過以下偽代碼來表示內(nèi)部邏輯:
While condition If child1.WhenCondition Then child1.Execute If child2.WhenCondition Then child2.Execute : If childN.WhenCondition Then childN.Execute End While 每個(gè)子活動(dòng)都有 WhenCondition 屬性。根據(jù)對(duì)指定條件的計(jì)算,可以在當(dāng)前的迭代中運(yùn)行或跳過活動(dòng)。請(qǐng)注重,假如子活動(dòng)沒有 WhenCondition 集合,子活動(dòng)將只能在第一次被執(zhí)行,并在后續(xù)的迭代中被跳過。假如需要,可以根據(jù)狀態(tài)變化的依存關(guān)系對(duì)所有條件進(jìn)行計(jì)算。
Using ts As New TransactionScope ... ts.Complete End Using TransactionScope 對(duì)象保證在出現(xiàn)故障的情況下,事務(wù)既可以被提交也可以被回滾,更為重要的是,它可以確定您需要一個(gè)本地事務(wù)還是一個(gè)分布式事務(wù),并登記所有必要的資源。當(dāng)代碼到達(dá)一個(gè)無法本地運(yùn)行的點(diǎn)時(shí),相應(yīng)地,TransactionScope 提升至分布式事務(wù)處理協(xié)調(diào)器 (DTC)。實(shí)施 ITransaction 接口的所有對(duì)象可以隨一個(gè)事務(wù)一起登記。該列表包括所有標(biāo)準(zhǔn) ADO.NET 2.0 數(shù)據(jù)提供程序,并且 Microsoft 消息隊(duì)列以兼容模式工作。
Dim service As New ExternalDataExchangeService runtime.AddService(service) Dim localService As New YourService() service.AddService(localService) 您可以配置 CallExternalMethod 活動(dòng)以調(diào)用由本地服務(wù)實(shí)施的接口的方法。為什么 CallExternalMethod 僅限于調(diào)用已知接口的方法?原因在于活動(dòng)不僅僅是代碼執(zhí)行者,而是旨在與 HandleExternalEvent 活動(dòng)一起實(shí)施與本地服務(wù)的雙向交流。借助 CallExternalMethod 活動(dòng),通過將 HandleExternalEvent 活動(dòng)加入工作流,您可以調(diào)用服務(wù)方法,處理服務(wù)引發(fā)的事件。
總結(jié)
活動(dòng)是工作流的構(gòu)造塊。通過在 Visual Studio 2005 設(shè)計(jì)器中撰寫活動(dòng),您可以創(chuàng)建工作流解決方案。與 ASP.NET 中的服務(wù)器控件和 Windows Forms 中的控件類似,工作流活動(dòng)是解決方案的精華所在并形成了開發(fā)人員的主要工具箱。Windows Workflow Foundation 提供了一些隨機(jī)活動(dòng)。在此,我要回顧一下涵蓋事務(wù)、并行和條件執(zhí)行、循環(huán)以及異常處理的活動(dòng)。wf.netfx3.com 上提供了解一些其他免費(fèi)活動(dòng)。將它們挑出來!