WF中的序列化与反序列化

来源:互联网 发布:国家统计局人口数据 编辑:程序博客网 时间:2024/05/29 10:56
 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 请查看无代码的工作流创作模式一文中.
 

2.然后将内存中的工作流序列化到文件中,代码如下:

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 Demoworkflow.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;}
就简单介绍这些。