程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> WF從入門到精通(第十六章):聲明式工作流

WF從入門到精通(第十六章):聲明式工作流

編輯:關於.NET

學習完本章,你將掌握:

1.理解過程式(imperative)工作流模型和聲明式(declarative)工作流模型之間的主要區別

2.創建聲明式工作流

3.使用XAML XML詞匯來創建工作流

4.調入基於XAML的工作流並執行

許多開發者或許並不知道WF既能用基於過程化的定義來執行工作流(使用工作流視圖設計器)也能用基於聲明式的定義來執行工作流(工作流使用XML來進行定義)。

每一種風格都有優點。當你使用我們貫穿本書已使用過的技術來創建你的工作流應用程序的時候,工作流模型實際上是被編譯進了一個可執行的程序集中。其優點是加載、執行工作流的速度快。

但這種風格也缺乏靈活性。盡管有為WF加入動態能力的辦法(這不包括在本書中),但通常你的工作流仍然要由你去編譯它們。假如你的業務處理邏輯變化了的話,除非你為工作流中的判定使用了聲明性規則(在第12章“策略和規則”中討論過),否則的話你將不得不修改你的工作流定義,重新進行編譯和部署,此外還伴隨著去執行所有相關的測試和驗證工作。

但是,工作流運行時有能力接受幾乎任何形式的工作流定義。你以前還不得不去寫一些代碼來把你提供的工作流定義轉化成工作流運行時能夠執行的模型。事實上,這些正是WF處理基於XML的工作流定義所要做的事。

正如你可能期望的,把你的工作流記錄進一個XML格式的文件中,這能讓你很容易地修改和重新部署。這就不用在Microsoft Visual Studio中重新編譯你的工作流,你可簡單地使用任何XML編輯器(甚至是Windows中的“Notepad”記事本程序)來修改基於XML的工作流定義並把它創建的工作流模型提供給工作流運行時。你甚至能有兩全其美的辦法:通過使用WF的工作流編譯器來編譯你的XML工作流定義。我們將在本章探討這些內容。

聲明式工作流——XML標記

首先,.NET 3.0中的聲明式應用程序(它包括WPF)的定義有著悠久的歷史。WPF開始提供聲明式編程的能力,它既可完全地進行聲明化也可進行部分聲明。你可完全地使用像XML應用程序標記語言或者XAML(讀作“zammel”)中的XML標記詞匯來封裝你的應用程序。或者,通過使用特殊的基於XAML的結構,你能把你應用程序的某部分編譯進程序集中並通過XAML來把它調入執行。你甚至能寫下C#代碼並把它嵌入到你的XAML定義中,或者把你的C#代碼放進代碼後置文件中,以便稍後執行它。

備注:你不能找到比Charles Petzold的最新著作:“應用程序 = 代碼 + 標記”(“Application = Code + Markup”,2006年微軟印刷)更好的在XAML和WPF方面的專著了。假如你對XAML論題的詳細細節感興趣的話,強烈建議你重新看看本書的第19章。

做下面的這個實驗其實只是為了好玩。在你的系統中創建一個新的文本文件,把它命名為Button.xaml。把列表16-1中的代碼輸入到該文件中並進行保存,然後雙擊該文件。因為你必須安裝.NET 3.0組件才能創建工作流應用程序,因此其實你也已經完成了對.xaml類型文件的注冊工作。Windows知道把XAML文件加載到你的Web浏覽器並顯示它。盡管它僅僅只有一個按鈕,但這是一個完整的WPF應用程序,雖然它很簡單。圖16-1顯示了使用Window XP中的IE 7.0來展示該按鈕的輸出效果。

<?xml version="1.0"?>
<Button xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Margin="36" Foreground="Blue" FontSize="36pt">
Hello,World!
</Button>

列表16-1展示一個按鈕的基於XAML的應用程序示例

圖16-1正在運行的基於XAML的按鈕

WF團隊也把這些理念一起融入到了WF中。雖然WF的XML遵循XAML命名空間的約定,但包含和WF相關的XML的文件名通常都使用.xoml文件擴展名來進行命名。這種做法能讓自動化工具把該文件解釋為一個工作流文件而不是一個外觀(presentation)文件。事實上,我們將在本章中使用的一個工具,它叫工作流編譯器(wfc.exe),在創建基於XAML的工作流時它要求使用.xoml類型的文件。

盡管列表16-1不是對工作流的聲明,但要仔細看看你看到的XML。注意該XML元素的名稱和.NET WPF類中支持的名稱是相同的,在本例子中它是Button。還值得一提的是該按鈕的屬性將由XAML文件進行解釋,它們是:FontSize,Margin和Foreground。通過改變這些屬性或者添加其它屬性,我們能非常容易地修改該按鈕的特性。

基於工作流的XAML文件也有同樣的特點。XML元素的名稱代表了像CodeActivity或者IfElseActivity之類的活動類型。和你可能期望的一樣,每一個元素能夠包含它們的屬性以及它們的值。至於工作流的結構,組合活動將會有子XML元素,而基本活動則沒有。

聲明命名空間與命名空間組織

XML通常對命名空間非常敏感,XAML也不例外。有幾個命名空間是關鍵的,這些包括和工作流相關的命名空間和與.NET自身相聯系的命名空間。

你的XAML文件必須包括的主要的命名空間是http://schemas.microsoft.com/winfx/2006/xaml,它通常使用x前綴。在XML文件中,命名空間的聲明看起來和下面這些相似:

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

基於工作流的XAML文件也必須包括工作流的命名空間:http://schemas.microsoft.com/winfx/2006/xaml/workflow。如果有命名空間的前綴的話,約定它為wf,但在基於工作流的XAML文件中你通常為工作流的命名空間指定默認的命名空間(也就是省略它的前綴):

xmlns=http://schemas.microsoft.com/winfx/2006/xaml/workflow

它是一個罕見的工作流,因為它不需要訪問.NET運行時,但這些是怎樣在XML文件中做到的呢?哦,其實該文件並不調用任何和.NET運行時相關的東西——工作流運行時會為你做這些。該XML文件僅僅需要識別出它需要的.NET公共語言運行時(CLR)的組件,這些東西要麼由.NET本身來提供,要麼是你用基於XML的工作流所包含的自定義對象。為了識別出這些行為,可使用一個特定的句法規則來創建一個XML命名空間。

XAML將使用的CLR命名空間可通過使用兩個關鍵字來創建:clr-namespace和assembly=。例如,如果你想在你的基於XAML的工作流中使用Console.WriteLine,你就需要為.NET的命名空間System創建如下的一個命名空間:

xmlns:sys="clr-namespace:System;assembly=System"

但是當你在基於XAML的工作流中創建你想使用的程序集時,僅僅創建程序集,為它指定命名空間,然後在工作流中包含它們是不夠的。工作流運行時將加載你指定的程序集,但是它需要使用一個附加的特性:XmlnsDefinition特性,它自動加載對象並執行。

例如,考慮你想在你的基於XAML的工作流中使用下面這個活動:

public class MyActivity : Activity
{
...
}

假設該類在MyAssembly程序集的MyNamespace命名空間中,則把它引進基於XAML的工作流中去的代碼就應該和列表16-2中展示的一樣。

列表 16-2使用XmlnsDefinition特性的例子

using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.ComponentModel;
using System.Workflow.Activities;
[assembly:XmlnsDefinition("urn:MyXmlNamespace","MyNamespace")]
namespace MyNamespace
{
public class MyActivity : Activity
{
// Not a very active activity!
}
}

引用這個類的XML如下:

xmlns:ns0="urn:MyXmlNamespace"

命名空間使用的字符串並不重要,這也許令人驚奇。重要的是在聲明命名空間的時候,在XmlnsDefinition中聲明的命名空間字符串要和在XML文件中使用的命名空間字符串相同。在XML中使用的命名空間必須是唯一的。也就是說,它們必須和XML文件中已經使用的現有的命名空間有所不同。我們將在接下來的一節對這進行更多的體會。

備注:假如你對XML命名空間比較生疏,則下面的網址或許對你有所幫助:http://msdn.microsoft.com/XML/Understanding/Fundamentals/default.aspx?pull=/library/en-us/dnxml/html/xml_namespaces.asp。

創建並執行基於XAML的工作流

在XML文件中定義的工作流能以兩種方式執行:通過工作流運行時直接執行或者編譯為程序集。對於直接執行XML文件中包含的工作流來說,首先把XML加載進XmlTextReader後,只需簡單地調用使用XmlTextReader作為參數的工作流運行時的CreateWorkflow方法即可去執行該工作流。編譯XML文件涉及到工作流編譯器wfc.exe的使用。我們通過使用你在圖16-2中看到的這個簡單的工作流來看看這兩種情形。

圖16-2基於XAML的工作流定義實驗所用的簡單工作流

創建一個直接執行XML的新工作流應用程序

1.下載本章源代碼,打開DirectXml-Workflow目錄中的解決方案。

2.在我們對Program.cs文件進行修改以便執行我們的工作流前,我們先創建該工作流本身。在Visual Studio的解決方案資源管理器中右鍵單擊DirectXmlWorkflow項目,依次選擇“添加”、“新建項”。當“新建項”對話框出現後,從列表中選擇“XML 文件”並把它命名為“Workflow1.xml”。最後點擊“添加”。

備注:Visual Studio將創建一個擴展名為.xml的文件。這時還不能把它改為.xoml,其原因是讓該XML文件能在工作流視圖設計器中進行編輯。.xoml文件擴展名是一個約定,對於WF工作流運行時來說這不是必須的,因此我們實際上只是把Visual Studio作為一個簡單的XML編輯器來使用(其實這裡可使用任何XML編輯器)。當應用程序執行時要確保該XML文件已被復制到該應用程序的執行路徑下以便代碼能找到該文件。

3.在解決方案資源管理器中選中該Workflow1.xml文件以便在屬性面板中激活它的文件屬性。

4.修改Workflow1.xml文件的“復制到輸出目錄”屬性選項,把它從“不復制”修改為“如果較新則復制”。

5.添加下面的XML內容到該文件中,然後進行保存。

<SequentialWorkflowActivity x:Name="Workflow1"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<SequenceActivity x:Name="sequenceActivity1">
<DelayActivity TimeoutDuration="00:00:05" x:Name="delayActivity1" />
</SequenceActivity>
</SequentialWorkflowActivity>

6.打開Program.cs文件進行編輯。在已存在的using語句末尾添加下面的using語句。

using System.Xml;

7.查看代碼,找到下面這行代碼:

Console.WriteLine("Waiting for workflow completion.");

8.在你上一步驟找到的代碼下面添加下面的代碼,以便能去調用你剛才創建的基於XAML的工作流。

// Load the XAML-based workflow
XmlTextReader rdr = new XmlTextReader("Workflow1.xml");

9.在你剛添加的代碼下添加如下這些創建工作流實例的代碼:

// Create the workflow instance.
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(rdr);
// Start the workflow instance.
instance.Start();

10.編譯該解決方案,糾正任何編譯錯誤。

11.按下Ctrl+F5或者F5鍵執行該應用程序,你將看到下面的執行結果。

你能以這種方式創建一些相當復雜的工作流。但是,它只局限於以下幾個方面。首先,盡管有在被調用的工作流內部執行C#代碼的機制,但如果沒特別要求的話,最好還是創建自定義的程序集來容納你想執行的代碼。其次,如果沒有首先創建一個自定義的根活動(root activity)來接受你輸入的參數的話,你就不能把參數傳到該工作流中。對於這些限制,或許將來的某些時候會有所改變,但對於現在來說就只能這樣。在本章的晚些時候我們將創建一個自定義的程序集來進行演示。

但是,有一個中間的步驟是把你的基於XAML的工作流編譯進一個程序集中,以便你能進行引用並執行。為了編譯該基於XAML的XML文件,我們將使用工作流的編譯器:wfc.exe。

備注:想了解wfc.exe的更多知識的話,可看看:msdn2.microsoft.com/en-us/library/ms734733.aspx。

創建執行一個對XML進行了編譯的新工作流應用程序

1.下載本章源代碼,打開CompiledXmlWorkflow目錄中的解決方案。

2.和前一個示例中的第2個步驟一樣,添加一個新的Workflow1.xml文件。因為你將使用工作流編譯器來編譯該工作流,因此你不需要改變該文件的編譯器設置(也就是說不需要前一節的步驟3和步驟4)。

3.把下面的XML添加到Workflow1.xml文件中並進行保存:

<SequentialWorkflowActivity x:Name="Workflow1" x:Class="Workflow1"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<SequenceActivity x:Name="sequenceActivity1">
<DelayActivity TimeoutDuration="00:00:05" x:Name="delayActivity1" />
</SequenceActivity>
</SequentialWorkflowActivity>

盡管這些可能看起來和你在前一個示例中添加的XML相似,但有一個細微的差別:x:Class屬性。工作流編譯器需要它,因為當編譯工作流時編譯器將需要這個新類的名稱。

4.在解決方案資源管理器中把該文件的擴展名從.xml修改為.xoml。假如Visual Studio發出一個關於修改文件類型的警告提示的話,忽略它並盡情點擊“是”。wfc.exe工具不接受以.xml作為擴展名的XML文件,它們必須使用.xoml作為文件擴展名。從“文件”菜單中選擇“保存 Workflow1.xoml”或者按下Ctrl+S來保存該文件。

5.在Windows中打開命令提示符cmd窗口。

6.在命令提示符中輸入:cd \Workflow\Chapter16\CompiledXmlWorkflow\CompiledXmlWorkflow,然後按下回車鍵改變相對目錄。在該目錄中將能直接訪問到該Workflow1.xoml文件。

7.在命令提示符中輸入"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\Wfc.exe" workflow1.xoml,然後按下回車鍵。當然,這是假想Windows SDK是安裝到你C盤的Program Files目錄中的。假如你把Windows SDK安裝到了其它地方,則需要修改上面的目錄。

8.工作流編譯器應該執行並無錯誤發生。當它的編譯過程完成後,它會生成一個動態鏈接庫workflow1.dll,它的目錄位置和Workflow1.xoml所在的目錄位置是一樣的。你現在需要引用這個動態鏈接庫,因為它包含了你在第3步創建的XML文件中定義的工作流。為此,在解決方案資源管理器中的CompiledXmlWorkflow項目上點擊右鍵,然後選擇“添加引用”。當“添加引用”對話框彈出後,選擇“浏覽”選項卡,然後從列表中選中workflow1.dll,最後點擊“確定”。

9.該工作流現在就完成了,我們現在需要完成我們的主應用程序。打開Program.cs文件進行編輯,查看該文件的源代碼,找到下面這行代碼:

Console.WriteLine("Waiting for workflow completion.");

10.在上面這行代碼下添加如下這些代碼:

// Create the workflow instance.
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(typeof(Workflow1));
// Start the workflow instance.
instance.Start();

11.編譯本解決方案,糾正任何出現的編譯錯誤。

12.按下Ctrl+F5或者F5執行該應用程序,你將看到如下的執行結果。

你也可以創建一個代碼後置文件並把包含的代碼編譯進你的工作流程序集中,盡管本示例我們沒有使用它。按照約定,假如該XML文件使用.xoml作為文件擴展名,該代碼後置文件就使用.xoml.cs。wfc.exe工具能接受一系列的.xoml文件以及與它們相關聯的.xoml.cs文件,它將把所有這些文件都編譯進一個單獨的工作流程序集中,前提是編譯過程中沒有錯誤。

雖然從表面上看這是一個小細節,但是這個細節將妨礙你進行工作流的編譯。第一個示例中的工作流和第二個示例中的工作流之間的唯一差異是要向標記中附加x:Class屬性。缺少x:Class屬性的基於XAML的工作流對於直接執行來說只能作為候選。僅僅是添加x:Class屬性就意味著你必須使用wfc.exe來對基於XAML的工作流進行編譯。假如你試圖直接執行你的基於XML的工作流的話,其結果是將產生一個WorkflowValidationFailedException異常,這是最可能出現的問題。

編譯你的基於XAML的工作流的實例中最有意義的一件事發生在你需要把初始化的參數傳入到你的工作流的時候。直接執行基於XAML的工作流不能夠接受初始化的參數。為了演示這些,我們完全回到第一章“WF簡介”中,然後重新創建一個郵政編碼驗證的示例應用程序。但是,我們將在XML中宿主該工作流而不是直接用C#代碼的方式。我們將使用一個代碼後置文件,因為我們還有條件要去進行判定,還有代碼要去執行。

備注:你能直接使用x:Code元素來把代碼直接放進XML的標記中。假如你對這些感興趣的話,可看看msdn2.microsoft.com/en-gb/library/ms750494.aspx。

創建一個編譯了XML的接受初始化參數的新工作流應用程序

1.在已經下載的本章源代碼中打開PCodeXaml目錄中的解決方案。

2.和前面的步驟一樣,添加一個新的Workflow1.xml文件。你不需要改變該文件的編譯器設置。事實上,一旦基於XAML的工作流完成並編譯後,我們將從項目中移除這個文件(也包括它的代碼後置文件),以便防止疏忽而導致編譯器產生警告信息。

3.向Workflow1.xml文件中添加下面的XML內容並保存它:

<SequentialWorkflowActivity x:Class="Workflow1" x:Name="Workflow1" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<IfElseActivity x:Name="ifElseActivity1">
<IfElseBranchActivity x:Name="ifElseBranchActivity1">
<IfElseBranchActivity.Condition>
<CodeCondition Condition="EvaluatePostalCode" />
</IfElseBranchActivity.Condition>
<CodeActivity x:Name="codeActivity1" ExecuteCode="PostalCodeValid" />
</IfElseBranchActivity>
<IfElseBranchActivity x:Name="ifElseBranchActivity2">
<CodeActivity x:Name="codeActivity2" ExecuteCode="PostalCodeInvalid" />
</IfElseBranchActivity>
</IfElseActivity>
</SequentialWorkflowActivity>

4.在解決方案資源管理器中把Workflow1.xml的文件擴展名從.xml修改為.xoml並保存該文件。

5.接下來添加代碼後置文件。在解決方案資源管理器中的PCodeXaml項目的名稱上單擊鼠標右鍵,選擇“添加”,然後選擇“類”。在“名稱”中輸入Workflow1.xoml.cs,最後點擊“添加”。

6.向文件中添加下面的代碼,完全替換Visual Studio為你添加的內容。然後保存這個你剛剛創建的文件。

Workflow1.xoml.cs

using System;
using System.Workflow.Activities;
using System.Text.RegularExpressions;
public partial class Workflow1 : SequentialWorkflowActivity
{
    private string _code = "";
    public string PostalCode
    {
        get { return _code; }
        set { _code = value; }
    }
    private void EvaluatePostalCode(object sender, ConditionalEventArgs e)
    {
        string USCode = @"^(\d{5}$)|(\d{5}$\-\d{4}$)";
        string CanadianCode = @"[ABCEGHJKLMNPRSTVXY]\d[A-Z] \d[A-Z]\d";
        e.Result = (Regex.IsMatch(_code, USCode) ||
                    Regex.IsMatch(_code, CanadianCode));
    }
    private void PostalCodeValid(object sender, EventArgs e)
    {
        Console.WriteLine("The postal code {0} is valid.", _code);
    }
    private void PostalCodeInvalid(object sender, EventArgs e)
    {
        Console.WriteLine("The postal code {0} is *invalid*.", _code);
    }
}

備注:這些代碼應該看起來比較熟悉。我是完全從第1章中的PCodeFlow應用程序和工作流中的原始代碼中復制粘貼過來的。

7.選擇“文件”菜單中的“全部保存”,或者按下Ctrl+Shift+S。

8.打開一個命令提示符窗口,在命令提示符中輸入:cd \Workflow\Chapter16\PCodeXaml\PCodeXaml,然後按下Enter改變當前的工作目錄。

9.在命令提示符中輸入:"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\Wfc.exe" workflow1.xoml workflow1.xoml.cs,然後按下回車鍵。

10.工作流編譯器會把XML和C#文件都匯集到一起。當它完成編譯後,它會再次生成一個名稱為workflow1.dll的動態鏈接庫,你現在應對它進行引用。在解決方案資源管理器中的PCodeXaml項目的名稱上單擊右鍵,然後選擇“添加引用”。在“添加引用”對話框彈出後,選擇“浏覽”選項卡,從列表中選中workflow1.dll,最後點擊“確定”。

11.回到主應用程序,選中Program.cs文件進行修改。在該文件中找到下面這行代碼:

Console.WriteLine("Waiting for workflow completion.");

12.在剛剛找到的代碼下添加如下這些代碼:

// Create the execution parameters
Dictionary<string, object> parms = new Dictionary<string, object>();
parms.Add("PostalCode", args.Length > 0 ? args[0] : "");
// Create the workflow instance.
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(typeof(Workflow1), parms);
// Start the workflow instance.
instance.Start();

13.這個項目有個小問題。你引用了workflow1.dll程序集,但是在代碼後置文件中也存在有創建該Workflow1類的代碼。這就造成了存在兩個名稱都為Workflow1的類實例的沖突。因為你想在已編譯的程序集中進行類的定義,因此需要在解決方案資源管理器中右鍵點擊Workflow1.xoml和Workflow.xoml.cs文件,然後選擇“從項目中排除”來移除它們。

14.編譯該解決方案,糾正任何可能出現的錯誤。

15.為了測試該應用程序,我們將使用命令提示符窗口。把當前目錄更改到Debug目錄(假如你編譯應用程序的模式使用的是Release模式的話,則要更改到Release)。為此,在命令提示符中輸入:cd bin\Debug然後按下Enter回車鍵(假如你以Release模式編譯的話需要把Debug改為Release)。

16.在命令提示符中,輸入PCodeXaml 12345並按下回車鍵。你會看到下面這些應用程序的輸出結果:

17。為了試試讓程序輸出否定的結果,在命令提示符中輸入PCodeXaml 1234x並按下Enter回車鍵。你會得到下面的輸出結果:

在本章我們將創建最後一個示例,它涉及到一個讓我們能對XmlnsDefinition進行演練的自定義的類

創建一個新的帶有自定義活動的基於XAML的工作流應用程序

1.在已經下載的本章源代碼中打開XmlnsDefFlow目錄中的解決方案。

2.添加一個新的名稱為Workflow1.xml的文件。但是你不需要更改該文件的編譯器設置或者對它進行重新命名。

3.在Workflow1.xml文件中添加下面的XML內容,然後進行保存:

<SequentialWorkflowActivity x:Class="Workflow1" x:Name="Workflow1"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow"
xmlns:custom="urn:PrintMessage">
<custom:PrintMessageActivity x:Name="printMessageActivity1"
custom:Message="Hello from the custom assembly!"/>
</SequentialWorkflowActivity>

4.在解決方案資源管理器中把該文件的擴展名從.xml改為.xoml,然後忽略彈出的警告信息,最後保存該文件。工作流現在就完成了,但注意要在XML標記中引用PrintMessageActivity,它是你需要去創建的一個新的自定義活動。為此,在解決方案資源管理器中添加一個新項目,從Workflow項目類型中選擇“工作流程活動庫”,在項目的名稱中輸入XmlnsDefLib。

5.Visual Studio會創建一個名稱為Activity1的工作流活動。在解決方案資源管理器中把Activity1.cs文件的名稱重命名為PrintMessageActivity.cs。

6.在代碼編輯視圖中打開該活動的源文件准備進行編輯。

7.該活動當前派生於SequenceActivity。現需要修改該活動派生的基類為Activity。該類定義應如下所示:

public partial class PrintMessageActivity: Activity

8.在構造器的下面添加如下這些代碼:

protected override ActivityExecutionStatus
Execute(ActivityExecutionContext executionContext)
{
// Print message to screen
Console.WriteLine(this.Message);
return ActivityExecutionStatus.Closed;
}
public static DependencyProperty MessageProperty =
DependencyProperty.Register("Message", typeof(System.String),
typeof(XmlnsDefLib.PrintMessageActivity));
public string Message
{
get
{
return ((System.String)(base.GetValue(
XmlnsDefLib.PrintMessageActivity.MessageProperty)));
}
set
{
base.SetValue(
XmlnsDefLib.PrintMessageActivity.MessageProperty, value);
}
}

9.現在添加XmlnsDefinition特性。就在命名空間聲明的前面,插入這些代碼:

[assembly:XmlnsDefinition("urn:PrintMessage","XmlnsDefLib")]

備注:假如你正在一個大應用程序中使用該活動,或者要分發給客戶或者其它外部用戶使用,可以使用包含你公司名稱的命名空間URI、產品組、項目或者其它典型的唯一的值來避免命名空間的歧義。當使用XML工作時,這通常被認為是最佳實踐。

10.編譯XmlnsDefLib項目以便生成一個能被工作流編譯器引用的DLL。

11.盡管我們將執行的是一個基於XAML的工作流,但工作流運行時仍然需要去訪問你剛剛創建的PrintMessage活動。因此,需要為XmlnsDefFlow項目添加對XmlnsDefLib的項目級引用。

12.和前面的示例應用程序一樣,打開一個命令提示符窗口。

13.在命令提示符中輸入cd \Workflow\Chapter16\XmlnsDefFlow\XmlnsDefFlow,然後按下Enter回車鍵來改變當前的工作目錄。Workflow1.xoml文件現在就可在該目錄下直接進行訪問。

14.在目錄提示符中輸入"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\Wfc.exe" workflow1.xoml /r:..\XmlnsDefLib\bin\Debug\XmlnsDefLib.dll,然後按下Enter回車鍵。和前面一樣,如果你把Windows SDK安裝到了其它地方,你需要使用你所安裝的目錄去執行wfc.exe,並且,假如你以Release的方式來編譯XmlnsDefLib項目的話,你也需要使用Release來替換Debug。

15.工作流編譯器執行時應該不會出現錯誤。它會在和Workflow1.xoml的相同目錄下生成一個動態鏈接庫workflow1.dll。你現在需要在你的主應用程序中引用該庫,因為它包含了你在第三步創建的XML文件中所定義的工作流。

16.隨著工作流的完成,我們要回到主應用程序中。在解決方案資源管理器中選中Program.cx文件,假如它沒有打開的話需要打開它。查看該文件,找到下面這行代碼:

Console.WriteLine("Waiting for workflow completion.");

17.在你剛剛找到的代碼下添加如下這些代碼:

// Create the workflow instance.
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(typeof(Workflow1));
// Start the workflow instance.
instance.Start();

18.編譯本解決方案,糾正任何出現的編譯錯誤。

19.按下Ctrl+F5或者F5執行該應用程序。你將看到如下的這些輸出結果。

備注:即使我們這裡創建了四個應用程序,我也沒有完全清楚地說明聲明式工作流定義方面的所有相關內容。假如你對這些感興趣的話,你可在MSDN上找到大量的論文:msdn.microsoft.com/msdnmag/issues/06/01/windowsworkflowfoundation/。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved