WF随笔系列之二 架构、编译、序列化
WF随笔系列之二,我们谈三个话题
1.Windows Workflow Foundation架构图
-----Workflow与host交互的例子
2.Windows Workflow Foundation的编译
3.Windows Workflow Foundation Serialization话题
------如何序列化Workflow和以及反序列化
2.1 Windows Workflow Foundation架构图:
补充,运行时引擎:
其实,在完成、失败和空闲的几种工作流实例的状态下,工作流运行时引擎应该表现出几种不同的事件。
如:
- WorkflowAborted
- WorkflowCompleted
- WorkflowCreated 更多[事件和事件说明]
事实上,workflow不是孤立运行的。因为WF在一个工作流实例和它的host之间提供了一些机制可以相互通信。那在工作流的内部或者外部,也提供很多的通讯方法能够让你快速和容易的传递数据,同时在一个工作流的环境外部,也有许多的可定制的方法能够支持你处理额外的事件和调用。
2.2 Workflow与host交互的例子
首先,创建SequentialConsoleApplication工程,然后在Workflow1.cs[Design]拖一个Code,双击codeActivity1,在后台代码中,建立三个私有字段
*OutputResultpublic int C { get { return C; } }
public int B { set { B = value; } }
public int A { set { A = value; } }
在ExecuteCode方法
{
C = A + B;
Console.WriteLine("At First,ExecuteCodeActivity1");
}
在Program.cs Main方法中
1. 声明一个 Dictionary<string, object>
2. 针对以上codeActivtiy1.cs建立字段,添加A,B元素的Value
parameters["A"] = 11;
parameters["B"] = 22;
3. 完成CreateWorkflow,以及WorkflowCompleted事件
instance.Start();
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) { Console.WriteLine(e.OutputParameters["C"]); };
至此,Workflow与host的Communication就完成。
当你在Host 应用程序中启动Workflow时,会直接调用WorkflowRuntime类中的CreateWorkflow方法,然后通过Dictionary<string, object>实例把需要操作的数据传输到Workflow中进行相应处理,最后在WorkflowCompleted事件中获得操作之后的结果。
2.3 Windows Workflow Foundation的编译
在.net程序集中编译工作流,一般是这样顺序
首先,workflow 编译,在这其中会包括Activity 验正,Activity代码的生成
然后, 经过语言编译(这里的语言指的C#,VB.net等等),最后形成.net程序集。
那编译完成之后,如何进行调用,其次就是实例化一个Runtime即可,然后调用startRuntime(),就OK了。
2.4 Windows Workflow Foundation Serialization话题
WWF FrameWork提供序列化的机制,workflow和activity都是可以进行序列化和反序列化。另外RuleConditions and RuleSets 也是可以序列化成 .rules 文件关联Workflow.
序列化类
System.Workflow.ComponentModel.Serialization
在Serialization命名空间下有三个Serializer:
- WorkflowMarkupSerializer
此类是Windows Workflow Foundation 所有序列化类的基类。你能使用其对workflows和activities进行序列化,序列化成xoml文件。当然,你也能把xoml文件反序列化成workflows和activites.
- ActivityMarkupSerializer
针对于Activity序列化
- CompositeActivityMarkupSerializer
针对于CompositeActivity序列化
当然也可以自定义序列化,如何自定义序列化?
直接在你要序列化类上面,加一个属性,然后在进行相应的Coding。
举例如下:
public class workflow
{
.//Coding
}
以上属性中第一参数是需要序列化的类,第二参数是代表第一个参数的基类型。
2.5 如何序列化Workflow和以及反序列化
- 首先建立一个WorkflowActivityLibrary项目
- 然后Activity1属性中,Base Class选择System.Workflow.ComponentModel.Activity
- 再建立一个WorkflowConsoleApplication项目
- 最后在Main方法直接Coding,代码如下
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("Workflow completed.");
waitHandle.Set();
};
//创建Workflow
Console.WriteLine("Creating workflow.");
SequentialWorkflowActivity workflow = new SequentialWorkflowActivity();
workflow.Name = "created workflow";
workflow.Description = "created workflow for XOML activation";
Activity activity = new Activity();
activity.Name = "ConsoleActivity1";
workflow.Activities.Add(activity);
.
}
序列化workflow到Xoml
using (XmlWriter writer = XmlWriter.Create(workflowFilename))
{
DesignerSerializationManager serializationManager = new DesignerSerializationManager();
///CreateSession()创建新序列化会话。
using (serializationManager.CreateSession())
{
serializer.Serialize(serializationManager, writer, workflow);
//当然要检查在序列化中发生错误时,就可以给于相应的提示信息或者记录日志什么的,
//那在DesignerSerializationManager类中有一个公共属性Errors,
//公共属性Errors是获取在序列化或反序列化期间发生的错误的列表。
if (serializationManager.Errors.Count > 0)
{
Console.WriteLine(String.Format("序列化时出错!{0}", serializationManager.Errors.Count));
return;
}
}
}
反序列化文件到workflow
WorkflowInstance deserializedWorkflow = null;
try
{
using (XmlReader reader = XmlReader.Create(workflowFilename))
{
deserializedWorkflow = workflowRuntime.CreateWorkflow(reader);
}
}
catch (WorkflowValidationFailedException exp)
{
. return;
}
序列化之后,会生成一个.Xoml 文件,以下是内容
<SequentialWorkflowActivity
x:Name="created workflow"
Description="created workflow for XAML activation" xmlns:ns0="clr-namespace:Microsoft.Samples.Workflow.WorkflowSerialization;Assembly=CustomActivity, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<ns0:Activity x:Name="Activity1" />
</SequentialWorkflowActivity>
其实大家看一下序列化之后的Xoml文件,可发现
1.在XOML中对象类型是为xml节点名 如:x:Name,Description
2.在XOML中对象属性值是xml节点的属性值 如:created workflow
3.在XOML中还包括<ns0:Activity>,这个就是我们在上面添加的子Activity.
其实,有关于序列化还是有许多可讲的,我在以后会进行穿插的。
CreateSession()补充:
序列化管理器中的大多数数据都是瞬态的,只在序列化会话期间存活。
当释放某个会话时,会认为序列化已经完成,并且会清除该瞬态。
这允许使用序列化管理器的一个实例序列化多个对象树。
有的状态(包括服务提供程序和添加到序列化管理器的任何自定义的序列化提供程序)是跨会话的。
引文:
DesignerSerializationManager 类基于序列化会话这一理念。
会话维护可由各种序列化程序访问的状态。当释放会话时,该状态会损坏。
这有助于确保序列化程序主要保持无状态,并且有助于清理已经损坏的序列化程序。
DesignerSerializationManager 类可实现三个目标:
它是一个简单的总控对象,可以用来对各种格式进行反序列化。
它是通用的,不绑定到任何特定格式。对于 CodeDOM 反序列化以及标记反序列化,它的使用方式相同。
它是可扩展的,并且支持在复制/粘贴和撤消/重复方案中使用的不同序列化方法。
设计时序列化与运行时对象序列化具有下列不同之处:
执行序列化的对象通常与运行时对象是分离的,因此,可从组件中移除设计时逻辑。
序列化方案假定将要创建完全初始化的对象,然后在反序列化期间通过属性和方法调用对其进行修改。
如果对象的属性具有从未在该对象上设置过的值(这些属性包含默认值),就不会对这些属性进行序列化。相反,反序列化流可能会有漏洞。
重点是序列化流中的内容的质量,而不是对象的完全序列化。
这表示,如果没有定义序列化对象的方法,则可以跳过该对象,否则会引发异常。
序列化引擎可以在这里提供试探法来确定可以忽略哪些失败以及哪些失败不可恢复。
序列化流具有的数据可能多于反序列化所需的数据。
例如,源代码序列化已将用户代码与反序列化对象图所需的代码混合。
对于反序列化,必须忽略该用户代码,而对于序列化,必须保留该用户代码。
Demo下载: WF序列化DEMO
后话:(有关于图示1)
那有关于out-of-the-box是什么?以及out-of-the-box Services中有哪几种Services.这些我留到下次再说。
好。结束。。。