通過XOML或者XAML的方式創建和啟動工作流
在Workflow Foundation中,提供了多種設計工作流的方式。例如:
1、純代碼的方式(C#)
2、代碼分離的方式(XOML+C#)
以上兩種,可以從Visual Studio提供的項目模板中選擇:
xoml是一種特殊的XML格式,它可以描述流程。例如下面這樣的一個流程:
<CodeActivity x:Name="codeActivity1" />
<IfElseActivity x:Name="ifElseActivity1">
<IfElseBranchActivity x:Name="ifElseBranchActivity1">
<CodeActivity x:Name="codeActivity2" />
</IfElseBranchActivity>
<IfElseBranchActivity x:Name="ifElseBranchActivity2">
<CodeActivity x:Name="codeActivity3" />
</IfElseBranchActivity>
</IfElseActivity>
</SequentialWorkflowActivity>
雖然上面這樣的XML確實可以描述流程,但流程所涉及的一些特殊邏輯,則可能還是需要寫代碼。這兩個部分,最終還是需要編譯成一個類型出來。所以,實際上上面的兩種方式沒有本質的區別。
這里要介紹的是一種純XOML的方式:我們能不能全部用XOML來實現對流程的定義?如果這樣的話,我們就可以實現更加動態化的流程,因為如果存在額外的代碼,就無需編譯,而是可以通過直接修改XOML文件就完成流程的修改。
答案是:可以的。但有一個前提,既然我們不想用代碼,那么流程中所使用的Activity就應該都是可以通過配置即可完成工作的。
通常,我們需要編寫自定義Activity來實現這樣的需求。例如,我們可以做一個最簡單的Activity,它只是根據用戶輸入的一個參數,負責在屏幕上打印一個消息。
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Linq;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace WorkflowConsoleApplication1
{
public partial class MyActivity :Activity
{
public MyActivity()
{
InitializeComponent();
}
public string Message { get; set; }
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
Console.WriteLine(Message);
return base.Execute(executionContext);
}
}
}
為了演示如何直接通過XOML定義的方式使用這個自定義Activity,我們可以通過下面的代碼生成一段XOML :
workflow.Activities.Add(new MyActivity() { Message = "Hello,World" });
var serializer = new WorkflowMarkupSerializer();
serializer.Serialize(
XmlWriter.Create("test.xoml",new XmlWriterSettings(){CloseOutput=true}), workflow);
以上代碼的意思是,創建一個SequenceActivity,并且在其中添加我們自定義的這個Activity。代碼執行完成之后,生成的那個test.xoml的內容如下:
<ns0:MyActivity Message="Hello,World" x:Name="myActivity1" />
</SequenceActivity>
這里請仔細觀察一下與之前那段xoml的區別:
1.頂層的Activity,不再包含x:Class定義。(因為現在沒有了代碼文件,Class就無從說起了)
2.內部所有的自定義Activity,都需要預先定義有關的namespace,引用到它們所在的Assembly
3.自定義Activity的設置,直接通過屬性完成
那么,如何利用上面這樣的定義,去創建并運行流程呢?
XmlReader.Create("test.xoml"));
instance2.Start();
如果我們需要修改流程定義,則直接可以修改那個XOML文件,而無需編譯程序。例如我們將Message修改為“Hello,Workflow”:
其實,只要我們愿意,我們甚至可以將這些定義的字符串保存在愛數據庫中,然后通過下面代碼創建并啟動流程:
//這里還可以從數據庫將該定義讀取出來
var reader = XmlReader.Create(new StringReader(definition));
var workflow = workflowRuntime.CreateWorkflow(reader);
workflow.Start();