WF中的工作流有两种方式,一种是代码的模式,还是一种就是.xoml的模式,这两者之间是可以进行相互转换的,这就是WF中提供的序列化
和反序列化支持。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; }
就简单介绍这些。
作者:生鱼片
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。