还是那句老话,Workflow 4.0和Workflow 3.0/3.5相比有很大的不同,其中之一就是Activity间数据交换方式的变化。
在3.0/3.5中,我们使用DependenceProperty,使用绑定的方式在不同的Property建立关联,由此实现数据的交换。这种方式的确很灵活,但是也带来不少弊病。比如所有的数据都存在同一个域中导致性能的下降,同时DependenceProperty的生命周期也是很让人困惑的问题,我不只一次的在论坛上听到有人提出对DependenceProperty的初始化时间提出疑问。
在4.0中,我们建立了一种更简洁的数据管理模式,变量(Variable)和参数(Argument)。这也是一种更符合大部分人编程习惯的数据模型。在传统的编程模式中,我们使用变量来存储数据,使用函数来封装程序的功能,使用参数和返回值来进行函数间的数据交换。
在Workflow中,Activity是封装功能的单元,我们可以理解为传统编程中的函数。而变量、参数的概念是类似的。我们来看一个例子。
一个C#的Hello World只有几行
在这个例子中我们建立了一个message变量,它的生命周期就是我们的HelloWorldSample这个函数,在函数开始时我们会对这个变量进行初始化,结束时会释放这个变量的资源。同时我们调用了一个叫做WriteLine的函数,这个函数有一个输入参数类型是string,在调用函数时我们将变量message作为具体的值传入WriteLine函数。如果将上面的代码转化为Workflow,你会发现这些概念是对应的。
下面我们来具体介绍Variable和Argument。
参数(Argument),Activity的I/O数据流接口
Argument是Activity的I/O接口,分为InArgument、OutArgument、InOutArgument。
可见域:定义Argument的Activity的Execute函数及其所有实现子活动(Implementation Child Activity )。
生命周期:等同于定义它的Activity。
InArgument
用于向Activity传入数据,只能对其进行取值操作。它可以使用Activity<T>、常数、Lambda Expression或者Variable作为表达式。
OutArgument
用于向Activity外部传出数据,只能对其进行赋值操作。它可以使用Activity<Location<T>>、Lambda Expression或者Variable作为表达式。
InOutArgument
用于向Activity传入或传出数据,可对其进行取值和赋值操作。它可以使用Activity<Location<T>>、Lambda Expression或者Variable作为表达式。
RequiredArgumentAttribute
默认情况下,在使用Activity时不需要对每一个Argument赋值,但是你可以为你的 Argument加上RequiredArgumentAttribute,用于表示必须在定义Workflow时必须为这个Argument赋初值。Runtime在创建Workflow实例时会对所有Argument进行检测,如果某个RequiredArgument没有赋值,将会抛出ValidationException。
例子:
变量(Variable),Workflow中的数据公共存储单元
Variable是用于存放数据的单元,Variable分为普通变量(Variable)实现变量(Implementation Variable)两种。
生命周期:等同于定义它的Activity,在Activity开始执行时, Workflow Runtime会初始化所有定义在这个Activity中的变量,而在Activity结束时结束Variable的生命周期。
注意:
Variable的初始化是有顺序的,如果你不清楚当前 Activity对Variable的初始化顺序,不建议使用同一个Activity中定义的不同Variable进行相互的初始化。因为这种错误无法在设计时别检测,只有在运行时才能被发现。
在C#代码中,你可以使用下面代码
但在Workflow中下面代码可能会有潜在危险
因为var1在var2之后初始化,所以在运行时会得到异常说var1没有被初始化。但是如果你交换var1和var2的位置,就不会得到任何异常。
Variable的默认值的类型是System.Activites.Activity<T>。但你还可以用常数、Lambda Expression或者其他得Variable来初始化Variable。
除了类型(Type),名称(Name)和默认值(DefaultValue),Variable还有两个附加属性:只读(ReadOnly)和映射(Mapped)
只读(ReadOnly)
ReadOnly属性顾名思义,就是表示这个Variable在能在初始化时对其赋值,若试图在之后对其赋值,将会得到一个运行时的异常。
例如
以上Workflow会在运行时Assign时获得一个InvalidOperationException。
映射(Mapped)
被标志为Mapped属性的Variable,可在工作流实例持久化时对这个Variable进行查询,我将在Persistence章节中详细介绍。
普通变量(Variable)
一个典型的例子是Sequence得Variables属性。
可见域:定义Variable的Activity的所有普通子活动(Child Activity)。
下面是一个在自定义活动中使用Variable的例子:
注意:
你是无法在Activity的内部函数中或其实现子活动(Implementation Child Activity)中使用当前Activity所定义的普通变量。
实现变量(Implementation Variable)
Implantation Variable用于储存Activity的私有数据,它只能在定义它的Activity的内部函数中或Activity的实现子活动(Implementation Child Activity)中使用。
可见域:定义Variable的Activity的内部函数和所有实现子活动(Implementation Child Activity)。
下面是一个使用Implementation Variable的例子:
申明:以上部分中文为本人自行翻译,不代表微软官方翻译。