和反序列化支持。WF框架中以下幾個比較重要的類:
- WorkflowMarkupSerializer 類是序列化基礎結構中使用的序列化基類型。此類型爲序列化提供一些實現序列化規則的基本服務。該類
的Serialize方法可以從內存中的工作流模型創建Markup文件,Deserialize是它的相反操作。 - ActivityMarkupSerializer 類從 WorkflowMarkupSerializer 類繼承。此類型用於序列化所有基本活動。基本活動是複合活動之外的活動。
- CompositeActivityMarkupSerializer 類從 ActivityMarkupSerializer 類繼承,它爲複合活動提供序列化。CompositeActivityMarkupSerializer
增加更多方法以處理子活動,子活動可以使用它們自己的序列化提供程序來序列化。
1.下面的例子我們首先用代碼的方式創建一個工作流,代碼如下:
private static Activity CreateWorkflow() { CaryBaseWorkflow workflow = new CaryBaseWorkflow(); workflow.Name = "CaryWorkflow"; IfElseActivity ifElse = new IfElseActivity("ifElseActivity1"); IfElseBranchActivity branch = new IfElseBranchActivity("ifElseBranchActivity1"); //2.add a rule condition to the branch RuleConditionReference ruleCondition = new RuleConditionReference(); ruleCondition.ConditionName = "Condition"; branch.Condition = ruleCondition; //0.1.Code Condition //CodeCondition condition = new CodeCondition(); //ActivityBind bind = new ActivityBind("CaryWorkflow", "Condition"); //condition.SetBinding(CodeCondition.ConditionEvent, bind); //branch.Condition = condition; CaryPrintActivity caryPrintActivity = new CaryPrintActivity(); caryPrintActivity.Name = "caryPrintActivity1"; caryPrintActivity.Message = "您輸入的數字大於0"; branch.Activities.Add(caryPrintActivity); ifElse.Activities.Add(branch); branch = new IfElseBranchActivity("ifElseBranchActivity2"); caryPrintActivity = new CaryPrintActivity(); caryPrintActivity.Name = "caryPrintActivity2"; caryPrintActivity.Message = "您輸入的數字小於等於0"; branch.Activities.Add(caryPrintActivity); ifElse.Activities.Add(branch); workflow.Activities.Add(ifElse); return workflow; }
CaryBaseWorkflow 類和自定義活動CaryPrintActivity 請查看無代碼的工作流創作模式一文中.
private static void SerializeWorkflow(Activity workflow, String fileName) { try { using (XmlWriter xmlWriter = XmlWriter.Create(fileName)) { WorkflowMarkupSerializer markupSerializer= new WorkflowMarkupSerializer(); markupSerializer.Serialize(xmlWriter, workflow); } } catch (Exception e) { Console.WriteLine("Exception during serialization: {0}",e.Message); } }
3.然後我們可以使用如下代碼來測試,代碼如下:
static void Main(string[] args) { Activity workflow = CreateWorkflow(); SerializeWorkflow(workflow, "SerializedWorkflow.xoml"); using (WorkflowRuntime runtime = new WorkflowRuntime()) { AutoResetEvent waitHandle = new AutoResetEvent(false); runtime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); }; Console.WriteLine("開始執行工作流"); Dictionary<String, Object> paras = new Dictionary<string, object>(); paras.Add("Number", 6); try { //0.SerialezeWorkflow Demo XmlReader reader = XmlReader.Create("SerializedWorkflow.xoml"); WorkflowInstance instance = runtime.CreateWorkflow(reader, null, paras); instance.Start();
} catch (WorkflowValidationFailedException e) { foreach (ValidationError error in e.Errors) { Console.WriteLine(error.ErrorText); } } catch (Exception e) { Console.WriteLine(e.Message); } waitHandle.WaitOne(); Console.WriteLine("工作流執行完成\n\r"); } }
上面測試代碼中我們首先使用代碼的方式創建工作流,然後在將該工作流序列化到SerializedWorkflow.xoml中,最後我們使用該工作流。
4.上面的例子中我們直接將SerializedWorkflow.xoml加載到Runtime中,這樣只有當工作流實例執行的時候才能發現該工作流是否通過驗證。 我們還可以將該工作流編譯到DLL中,這樣就可以在編譯時對該工作流進行類型檢查。 4.1.編譯工作流時我們就創建了一個新的類型,所以在上面的CreateWorkflow中添加如下代碼設置X:Class屬性。
workflow.Activities.Add(ifElse); //1.Compile Demo workflow.SetValue(WorkflowMarkupSerializer.XClassProperty, "CaryWF.CompileWorkflowClass"); return workflow;
4.2.下面是編譯工作流的方法:
private static void CompileWorkflow(String fileName, String assemblyName) { WorkflowCompiler compiler = new WorkflowCompiler(); WorkflowCompilerParameters parameters = new WorkflowCompilerParameters(); parameters.OutputAssembly = assemblyName; parameters.ReferencedAssemblies.Add("CaryWFLib.dll"); //2.add the .rules file for this workflow as a resource //Rule的格式要固定這樣的 parameters.EmbeddedResources.Add("CaryWF.CompileWorkflowClass.rules"); WorkflowCompilerResults results = compiler.Compile(parameters, fileName); if (results.Errors.Count > 0) { foreach (System.CodeDom.Compiler.CompilerError error in results.Errors) { Console.WriteLine("編譯錯誤:行{0}: {1}",error.Line, error.ErrorText); } } }
4.3.注意上面將規則文件增加爲程序集的嵌入資源的時候,該規則的命名方式必須包含命名空間和工作流類。
4.4.除了使用WorkflowCompiler類對工作流進行編譯,我們還可以使用命令行的方式wfc.exe,格式如下:
wfc.exe SerializedWorkflow.xoml /target:assembly /debug:- /resource:CaryWF.CompileWorkflowClass.rules /reference:CaryWFLib.dll /out:CaryCompile.dll
5.再次測試,代碼如下:
static void Main(string[] args) { Activity workflow = CreateWorkflow(); SerializeWorkflow(workflow, "SerializedWorkflow.xoml"); //1.Compile Demo CompileWorkflow("SerializedWorkflow.xoml", "CaryCompile.dll"); using (WorkflowRuntime runtime = new WorkflowRuntime()) { AutoResetEvent waitHandle = new AutoResetEvent(false); runtime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { waitHandle.Set(); }; Console.WriteLine("開始執行工作流"); Dictionary<String, Object> paras = new Dictionary<string, object>(); paras.Add("Number", 6); try { Type workflowType = Type.GetType("CaryWF.CompileWorkflowClass,CaryCompile"); WorkflowInstance instance = runtime.CreateWorkflow(workflowType, paras); instance.Start(); } catch (Exception e) { Console.WriteLine(e.Message); } waitHandle.WaitOne(); Console.WriteLine("工作流執行完成\n\r"); } }
由於工作流進行了編譯,所以catch中的就不需要捕獲驗證失敗的特定異常了。
6.上面我們將內存中的工作流序列化到xoml文件中,我們也可以反序列化。
private static Activity DeserializeFromMarkup(String fileName) { Activity workflow = null; try { ServiceContainer container = new ServiceContainer(); TypeProvider provider = new TypeProvider(container); provider.AddAssembly(typeof(CaryWFLib.CaryBaseWorkflow).Assembly); container.AddService(typeof(ITypeProvider), provider); DesignerSerializationManager dsm= new DesignerSerializationManager(container); using (dsm.CreateSession()) { using (XmlReader xmlReader = XmlReader.Create(fileName)) { //deserialize the workflow from the XmlReader WorkflowMarkupSerializer markupSerializer = new WorkflowMarkupSerializer(); workflow = markupSerializer.Deserialize(dsm, xmlReader) as Activity; if (dsm.Errors.Count > 0) { foreach (WorkflowMarkupSerializationException error in dsm.Errors) { Console.WriteLine("Deserialization error: {0}", error); } } } } } catch (Exception e) { Console.WriteLine("Exception during deserialization: {0}",e.Message); } return workflow; }
就簡單介紹這些。