《WF编程》系列之12 – 编译工作流:XAML序列化

2.3.2.4 XAML序列化

 

我们可以从工作流实例中生成XAML,因为XAML本质上就是托管对象的XML序列化.下面的代码将输出正在运行的工作流的标记:

using (WorkflowRuntime runtime = new WorkflowRuntime())
{
using (StringWriter stream = new StringWriter())
{
using (XmlWriter writer = XmlWriter.Create(stream))
{
Type t = typeof(MyWorkflow);
WorkflowInstance instance = runtime.CreateWorkflow(t);
WorkflowMarkupSerializer serializer;
serializer = new WorkflowMarkupSerializer();
serializer.Serialize(writer, instance.GetWorkflowDefinition());
Console.WriteLine(stream.ToString());
}
}
}

 如果在之前包含自定义活动的工作流上运行这段代码,我们将获得下面的XAML.


需要注意的是,工作流定义现在还并不是透明可见的.当工作流编译器从工作流定义中创建了一个新的类型时,工作流定义变得固定且看不到内部活动顺序.但我们通过使用XAML激活机制仍然可以创建上面工作流的实例,激活机制将在下一节详述.XAML激活驱动XML并从标记指令中创建对象.当激活初始化MyWorkflow后,InitializeComponent方法将创建工作流中的所有活动,所以序列化不需要从XAML中获得显式的子活动列表.实例会像其它范例一样工作,并且会执行WriteLineActivity.

7 Comments

  1. afterglowlee 说道:

    请问大侠,我想用后台代码启动sharepoint Designer定义的工作流,但是在启动的时候在logs里面发现有编译错误SPNoCodeXomlCompiler.LoadXomlAssembly(String assmNameIn, SPWeb web),这个问���是不是跟编译有关?在sharepoint Designer里面定义的工作流也有类似<nso:MyWorkflow…..>的代码,那么Designer里定义的工作流是不是也可以手动编译呢?

  2. 笑煞天 说道:

    @ryan 1
    是不是你的xoml中使用了这个dll中的活动?如果是这样的话,你的xoml中必须添加dll中的命名空间,请参阅���http://www.cnblogs.com/xiaoshatian/archive/2007/04/06/702254.html

  3. ryan 1 说道:

    Windows workflow 反序列化
    已知道 workflow的dll,和xoml文件。怎样实例化,并运行这个工作流?
    无论是我直接添加进去Sharedworkflows.dll 还是用provider.addAssemblyReference方法加入��是一样的问题。我总是出现error:“Can not create workflow definition. Input markup is invalid”

    Here is the code:
    WorkflowRuntime workflowRuntime = new WorkflowRuntime();
    workflowRuntime.StartRuntime();

    XmlTextReader reader = new XmlTextReader(“C:\xxx.xoml”);
    try
    {
    instance = workflowRuntime.CreateWorkflow(reader);
    instance.Start();
    }
    catch (WorkflowValidationFailedException exp)
    {

    StringBuilder errors = new StringBuilder();

    foreach (ValidationError error in exp.Errors)
    {
    errors.AppendLine(error.ToString());
    }

    MessageBox.Show(errors.ToString(), "Validation errors");
    }

    XOML 文件如下:

    <SequentialWorkflowActivity x:Class="Sharedworkflows.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" Description="right">
    <IfElseBranchActivity.Condition>
    <CodeCondition Condition="IsNumberPositive" />
    </IfElseBranchActivity.Condition>
    <CodeActivity x:Name="codeNumberIsPositive" ExecuteCode="codeNumberIsPositive_ExecuteCode" />
    </IfElseBranchActivity>
    <IfElseBranchActivity x:Name="ifElseBranchActivity2" Description="wrong">
    <IfElseBranchActivity.Condition>
    <CodeCondition Condition="NotNumberPositive" />
    </IfElseBranchActivity.Condition>
    <CodeActivity x:Name="codeNumberNotPositive" ExecuteCode="codeNumberNotPositive_ExecuteCode" />
    </IfElseBranchActivity>
    </IfElseActivity>
    </SequentialWorkflowActivity>

  4. @ryan 1
    你的xoml中许多活动包含了隐藏代码,这样的话是不能直接用runtime加载的,runtime只能加载独立的xoml文件,就是说这个xoml文件不能和代码隐藏文件(.xoml.cs)相关联,所以你把那些ExecuteCode去掉就可以了。

  5. ryan 1 说道:

    谢谢,楼主的回复. 刚刚接触workflow. 我的目的是得到相关的workflow dll, xoml文件. 然后在其他project里面调用运行来执行操作. 现在只是测试.将来 dll, xoml还在数据库中保存.
    有朋友给我说, 要用no-code workflow才行.
    我现在用的是独立代码workflow( workflow.xoml.cs 包含business logic,就是1个简单的查看Input值大小)
    按你说的把ExecuteCode去掉的话,怎样把逻辑和xoml联系在一起?
    有没有合适的代码,让我看一下.
    在线等.谢谢.

  6. ryan 1 说道:

    我换了个写法.这样是不是适��于 code-behind workflow? 是不是我这种情况只能用xoml-only?

    XmlReader reader = XmlReader.Create(xomlpath);
    WorkflowMarkupSerializer wms = new WorkflowMarkupSerializer();
    Activity wf1 = wms.Deserialize(reader) as Activity;
    Dictionary(of String,Object) para = new Dictinonary(Of String,Object);
    para.add("’TheNumber’",1);
    NewInstance = WFRuntime.CreateWorkflow(wf1.GetType(),para);
    NewInstance.Start();

    markup没有报错,但是 找不到"TheNumber".

  7. @ryan 1
    请查阅http://www.cnblogs.com/xiaoshatian/archive/2007/04/06/702254.html
    以及
    http://www.cnblogs.com/xiaoshatian/archive/2007/04/25/726572.html

    找不到TheNumber是因为你的工作流定义中不包含公开可写的TheNumber属性。

Leave a Reply