《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.




Windie Chai @ 豆瓣
windiechai @ Twitter
windiechai @ 新浪微博
请问大侠,我想用后台代码启动sharepoint Designer定义的工作流,但是在启动的时候在logs里面发现有编译错误SPNoCodeXomlCompiler.LoadXomlAssembly(String assmNameIn, SPWeb web),这个问���是不是跟编译有关?在sharepoint Designer里面定义的工作流也有类似<nso:MyWorkflow…..>的代码,那么Designer里定义的工作流是不是也可以手动编译呢?
@ryan 1
是不是你的xoml中使用了这个dll中的活动?如果是这样的话,你的xoml中必须添加dll中的命名空间,请参阅���http://www.cnblogs.com/xiaoshatian/archive/2007/04/06/702254.html
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>
@ryan 1
你的xoml中许多活动包含了隐藏代码,这样的话是不能直接用runtime加载的,runtime只能加载独立的xoml文件,就是说这个xoml文件不能和代码隐藏文件(.xoml.cs)相关联,所以你把那些ExecuteCode去掉就可以了。
谢谢,楼主的回复. 刚刚接触workflow. 我的目的是得到相关的workflow dll, xoml文件. 然后在其他project里面调用运行来执行操作. 现在只是测试.将来 dll, xoml还在数据库中保存.
有朋友给我说, 要用no-code workflow才行.
我现在用的是独立代码workflow( workflow.xoml.cs 包含business logic,就是1个简单的查看Input值大小)
按你说的把ExecuteCode去掉的话,怎样把逻辑和xoml联系在一起?
有没有合适的代码,让我看一下.
在线等.谢谢.
我换了个写法.这样是不是适��于 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".
@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属性。