WF4.0 应用篇(一) Activity
流程设计器可加载的数据
Activity 对象 | 计器基于对象加载 |
Activity XAML | 设计器基于文件加载,也可以将XAML字串生成Activity加载 |
ActivityBuilder 对象 | 计器基于对象加载 |
ActivityBuilder XAML | 设计器基于文件加载,也可以将XAML字串生成ActivityBuilder对象加载 最好不要将XAML字串生成Activity加载,因为这时对象是DynamicActivity |
Activity结构
组合Activity
- 不需要定义类
- 由现有的Activity拼接而成
- 设计时不可添加动态Argument
- 可以由XAML表示,在XAML中没的Class标记,XAML结构与代码组合的结构一一对应
Activity | public Activity getActivity() { Sequence root = new Sequence{ DisplayName = "root" };
Variable<string> myVariable = new Variable<string>{ Name= "myVariable", Default="wxwinter"};
root.Variables.Add(myVariable);
Sequence body = new Sequence { DisplayName = "body" };
WriteLine writeLine = new WriteLine();
writeLine.Text = myVariable;
body.Activities.Add(writeLine);
root.Activities.Add(body);
return root; } |
宿主 | WorkflowApplication instance = new WorkflowApplication(getActivity());
instance.Run(); |
结果 | |
结构 | |
图例 | |
XAML | <Sequence mc:Ignorable="sap" DisplayName="root" sap:VirtualizedContainerService.HintSize="257,311" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Sequence.Variables> <x:Reference>__ReferenceID0</x:Reference> </Sequence.Variables> <sap:WorkflowViewStateService.ViewState> <scg:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">True</x:Boolean> </scg:Dictionary> </sap:WorkflowViewStateService.ViewState> <Sequence DisplayName="body" sap:VirtualizedContainerService.HintSize="235,187"> <sap:WorkflowViewStateService.ViewState> <scg:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">True</x:Boolean> </scg:Dictionary> </sap:WorkflowViewStateService.ViewState> <WriteLine sap:VirtualizedContainerService.HintSize="213,63"> <InArgument x:TypeArguments="x:String"> <VariableValue x:TypeArguments="x:String"> <VariableValue.Variable> <Variable x:TypeArguments="x:String" x:Name="__ReferenceID0" Default="wxd" Name="myVariable" /> </VariableValue.Variable> </VariableValue> </InArgument> </WriteLine> </Sequence> </Sequence> |
静态 Activity
- 需要定义类,Activity具有类名
- 在类中使用Execute方法实现功能
- 设计时不可添加动态Argument
- 可Variables,Activities,Body等在设计时可添加内容的区域
- 可以由XAML表示,在XAML中没的Class标记,XAML只表示该Activity与其属性,不表示其内部
- XAML脱离该类无法运行
Activity | public sealed class 静2态¬?Activity : CodeActivity {
public InArgument<string> myValue { get; set; }
protected override void Execute(CodeActivityContext context) {
string text = context.GetValue(this.myValue);
System.Console.WriteLine(text); } } |
宿主 | Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add("myValue", "wxwinter"); WorkflowApplication instance = new WorkflowApplication(getActivity(),dic);
instance.Run(); |
结果 | |
结构 | |
图例 | |
XAML | <静态Activity mc:Ignorable="sap" myValue="{x:Null}" sap:VirtualizedContainerService.HintSize="200,22" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" xmlns="clr-namespace:ActivityStructure.code;assembly=ActivityStructure.code" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" /> |
动态Activity
DynamicActivityProperty | |
ICustomTypeDescriptor | |
DynamicActivity | |
DynamicActivity<TResult> |
- DynamicActivity可以通过向Properties中添加DynamicActivityProperty以实现动态添加InArgument,OutArgument属性
- DynamicActivity可以通过Implementation关联要执行的Activity
- DynamicActivity的Properties中的InArgument可在创建实例时为其传入值
- DynamicActivity的Properties中的OutArgument可在实例完成时得到传出值
- DynamicActivity关联的Activity内部可以通过[VisualBasicValue]方式与Properties中的直绑定
- DynamicActivity不能保存为XAML,但可以将DynamicActivity的Implementation保存为XAML,该XAML没的参数.在使用该XAML创建实例时还要动态为其创建参数
Activity | public Activity getActivity() { DynamicActivity dynamicActivity = new DynamicActivity(); dynamicActivity.DisplayName = "myDynamicActivity";
dynamicActivity.Properties.Add(new DynamicActivityProperty { Name = "inValueA", Type = typeof(InArgument<int>), Value = new InArgument<int>() });
dynamicActivity.Properties.Add(new DynamicActivityProperty { Name = "inValueB", Type = typeof(InArgument<int>), Value = new InArgument<int>() });
dynamicActivity.Properties.Add(new DynamicActivityProperty { Name = "outValue", Type = typeof(OutArgument<int>), Value = new OutArgument<int>() });
dynamicActivity.Implementation =()=>createActivity();
return dynamicActivity;
} |
Activity createActivity() {
return new Sequence {
Activities = { new Assign<int> { To = new ArgumentReference<int> { ArgumentName = "outValue" }, Value = new VisualBasicValue<int>("(inValueA + inValueB) * 100") }, } }; } | |
宿主 | Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add("inValueA", 123); dic.Add("inValueB", 456);
IDictionary<string, object> results = WorkflowInvoker.Invoke(getActivity(), dic);
foreach (var v in results) { System.Console.WriteLine("{0}:{1}", v.Key, v.Value); } |
结果 | |
结构 | |
图例 |
无参数,只是Implementation部分,所以动态绑定部分有验证提升
|
XAML | 无参数,只是Implementation部分
<Sequence mc:Ignorable="sap" sap:VirtualizedContainerService.HintSize="222,146" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <sap:WorkflowViewStateService.ViewState> <scg:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">True</x:Boolean> </scg:Dictionary> </sap:WorkflowViewStateService.ViewState> <Assign x:TypeArguments="x:Int32" sap:VirtualizedContainerService.HintSize="200,22" Value="[(inValueA + inValueB) * 100]"> <Assign.To> <OutArgument x:TypeArguments="x:Int32"> <ArgumentReference x:TypeArguments="x:Int32" ArgumentName="outValue" /> </OutArgument> </Assign.To> </Assign> </Sequence> |
实现 Activity
- 通过继承Activity,构建Implementation实现.
- 只能通过继承Activity,其他从Activity派生的Activity不允许操作Implementation
- 设计时不可添加动态Argument
- 可以由XAML表示,在XAML中没的Class标记,XAML只表示该Activity与其属性,不表示其内部
- XAML脱离该类无法运行
Activity | public class 实º¦Ì现?Activity :Activity {
public InArgument<string> myValueA { get; set; }
public InArgument<string> myValueB { get; set; }
protected override void CacheMetadata(ActivityMetadata metadata) { Implementation = () => createActivity(); base.CacheMetadata(metadata); }
Activity createActivity() {
Sequence sequence = new Sequence();
sequence.Activities.Add(new WriteLine { Text = new VisualBasicValue<String>("myValueA") }); sequence.Activities.Add(new WriteLine { Text = new VisualBasicValue<String>("myValueB") });
return sequence;
}
} |
宿主 | Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add("myValueA", "wxwinter"); dic.Add("myValueB", "wxd"); WorkflowApplication instance = new WorkflowApplication(getActivity(), dic);
instance.Run(); |
结果 | |
结构 | |
图例 | |
XAML | <实现Activity mc:Ignorable="sap" myValueA="{x:Null}" myValueB="{x:Null}" sap:VirtualizedContainerService.HintSize="200,22" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces" xmlns="clr-namespace:ActivityStructure.code;assembly=ActivityStructure.code" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" /> |
构建 Activity
IDebuggableWorkflowTree | |
ActivityBuilder | |
ActivityBuilder<TResult> |
- 使用ActivityBuilder
- 设计器基可直接加载ActivityBuilder对象
- 设计器基可直接加载ActivityBuilder的XAML文件
- 使用ActivityBuilder的Implementation构建Activity
- ActivityBuilder的Properties中的InArgument可在创建实例时为其传入值
- ActivityBuilder的Properties中的OutArgument可在实例完成时得到传出值
- ActivityBuilder关联的Activity内部可以通过[VisualBasicValue]方式与Properties中的直绑定
- 生成的XAML具有Class标记,但并不会生成类,该标记是给VS生成Dll时使用的
- 设计时可添加动态Argument
- VS设计器使用的就是这种方式,designerView.Load(new ActivityBuilder())就产生了一个与VS一样的环节
- ActivityBuilder的XAML可用ActivityXamlServices生成Activity,是DynamicActivity类型
Activity | public ActivityBuilder getActivityBuilder() { //1 Sequence body = new Sequence();
//1.1 WriteLine writeLineA = new WriteLine(); writeLineA.DisplayName = "writeLineA"; writeLineA.Text = "hello lzm"; body.Activities.Add(writeLineA);
//1.2 WriteLine writeLineB = new WriteLine(); writeLineB.DisplayName = "writeLineB"; writeLineB.Text = new VisualBasicValue<string> { ExpressionText = "inputX+inputY" }; body.Activities.Add(writeLineB);
//1.3 Assign<string> assign = new Assign<string>(); assign.DisplayName = "assign"; assign.To = new VisualBasicReference<string> { ExpressionText = "output" }; assign.Value = new VisualBasicValue<string> { ExpressionText = "inputX+inputY" }; body.Activities.Add(assign);
//1.4 WriteLine writeLineC = new WriteLine(); writeLineC.DisplayName = "writeLineC"; writeLineC.Text = new VisualBasicValue<string> { ExpressionText = "output" }; body.Activities.Add(writeLineC);
//2 ActivityBuilder activityBuilder = new ActivityBuilder(); //2.1 activityBuilder.Name = "wxwinterClass"; //2.1 activityBuilder.Properties.Add(new DynamicActivityProperty { Name = "inputX", Type = typeof(InArgument<string>) }); activityBuilder.Properties.Add(new DynamicActivityProperty { Name = "inputY", Type = typeof(InArgument<string>) }); activityBuilder.Properties.Add(new DynamicActivityProperty { Name = "output", Type = typeof(OutArgument<string>) }); //2.3 activityBuilder.Implementation = body;
//3 return activityBuilder;
} |
string getXamlStringFromActivityBuilder(ActivityBuilder activityBuilder) { string xamlString = "";
StringBuilder stringBuilder = new StringBuilder();
System.IO.StringWriter stringWriter = new System.IO.StringWriter(stringBuilder);
System.Xaml.XamlSchemaContext xamlSchemaContext = new System.Xaml.XamlSchemaContext();
System.Xaml.XamlXmlWriter xamlXmlWriter = new System.Xaml.XamlXmlWriter(stringWriter, xamlSchemaContext);
System.Xaml.XamlWriter xamlWriter = System.Activities.XamlIntegration.ActivityXamlServices.CreateBuilderWriter(xamlXmlWriter);
System.Xaml.XamlServices.Save(xamlWriter, activityBuilder);
xamlString = stringBuilder.ToString();
return xamlString;
} | |
public Activity getActivity() { string xamlString = getXamlStringFromActivityBuilder(getActivityBuilder());
System.IO.StringReader stringReader = new System.IO.StringReader(xamlString);
Activity activity = System.Activities.XamlIntegration.ActivityXamlServices.Load(stringReader);
return activity;
} | |
宿主 | System.Collections.Generic.Dictionary<string, object> p = new System.Collections.Generic.Dictionary<string, object>(); p.Add("inputX", "wxd"); p.Add("inputY", "lzm");
System.Collections.Generic.IDictionary<string, object> r = WorkflowInvoker.Invoke(getActivity(), p, new TimeSpan(0, 0, 0)); foreach (var item in r) { System.Console.WriteLine(item); } |
结果 | |
结构 | |
图例 | |
XAML | <Activity mc:Ignorable="sap" x:Class="wxwinterClass" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <x:Members> <x:Property Name="inputX" Type="InArgument(x:String)" /> <x:Property Name="inputY" Type="InArgument(x:String)" /> <x:Property Name="output" Type="OutArgument(x:String)" /> </x:Members> <sap:VirtualizedContainerService.HintSize>275,495</sap:VirtualizedContainerService.HintSize> <mva:VisualBasic.Settings>Assembly references and imported namespaces serialized as XML namespaces</mva:VisualBasic.Settings> <Sequence sap:VirtualizedContainerService.HintSize="235,455" mva:VisualBasic.Settings="Assembly references and imported namespaces serialized as XML namespaces"> <sap:WorkflowViewStateService.ViewState> <scg:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">True</x:Boolean> </scg:Dictionary> </sap:WorkflowViewStateService.ViewState> <WriteLine DisplayName="writeLineA" sap:VirtualizedContainerService.HintSize="213,63" Text="hello lzm" /> <WriteLine DisplayName="writeLineB" sap:VirtualizedContainerService.HintSize="213,63" Text="[inputX+inputY]" /> <Assign x:TypeArguments="x:String" DisplayName="assign" sap:VirtualizedContainerService.HintSize="213,22" To="[output]" Value="[inputX+inputY]" /> <WriteLine DisplayName="writeLineC" sap:VirtualizedContainerService.HintSize="213,63" Text="[output]" /> </Sequence> </Activity> |
VS的Activity
VS设计器使用了的是[构建 Activity]创建流程
但与[构建 Activity]方式又有不同,VS不是基于ActivityBuilder的XAML的实例创建流程的,而是将
ActivityBuilder的XAML生成了Dll,方式如下
将ActivityBuilder的XAML中的Class标记做为类名,
将ActivityBuilder的XAML由
<Activity mc:Ignorable="sap" x:Class="WorkflowConsoleApplication2.Workflow1" this:Workflow1.myProperty="myOut" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:this="clr-namespace:WorkflowConsoleApplication2" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <x:Members> <x:Property Name="myIn" Type="InArgument(x:String)" /> <x:Property Name="myOut" Type="OutArgument(x:String)" /> <x:Property Name="myProperty" Type="x:String" /> </x:Members> <sap:VirtualizedContainerService.HintSize>305,326</sap:VirtualizedContainerService.HintSize> <mva:VisualBasic.Settings>Assembly references and imported namespaces for internal implementation</mva:VisualBasic.Settings> <Sequence sad:XamlDebuggerXmlReader.FileName="e:\myconfig\documents\visual studio 2010\Projects\WorkflowConsoleApplication2\WorkflowConsoleApplication2\Workflow1.xaml" sap:VirtualizedContainerService.HintSize="265,286"> <sap:WorkflowViewStateService.ViewState> <scg3:Dictionary x:TypeArguments="x:String, x:Object"> <x:Boolean x:Key="IsExpanded">True</x:Boolean> </scg3:Dictionary> </sap:WorkflowViewStateService.ViewState> <WriteLine sap:VirtualizedContainerService.HintSize="243,63" Text="[myIn]" /> <Assign sap:VirtualizedContainerService.HintSize="243,59"> <Assign.To> <OutArgument x:TypeArguments="x:String">[myOut]</OutArgument> </Assign.To> <Assign.Value> <InArgument x:TypeArguments="x:String">wxwinter</InArgument> </Assign.Value> </Assign> </Sequence> </Activity> |
转换为Activity格式的XAML
<?xml version="1.0" encoding="utf-8"?> <this:Workflow1 this:myProperty="myOut" mva:VisualBasic.Settings="Assembly references and imported namespaces for internal implementation" xmlns="http://schemas.microsoft.com/netfx/2009/xaml/activities" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mv="clr-namespace:Microsoft.VisualBasic;assembly=System" xmlns:mva="clr-namespace:Microsoft.VisualBasic.Activities;assembly=System.Activities" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:s1="clr-namespace:System;assembly=System" xmlns:s2="clr-namespace:System;assembly=System.Xml" xmlns:s3="clr-namespace:System;assembly=System.Core" xmlns:sa="clr-namespace:System.Activities;assembly=System.Activities" xmlns:sad="clr-namespace:System.Activities.Debugger;assembly=System.Activities" xmlns:sap="http://schemas.microsoft.com/netfx/2009/xaml/activities/presentation" xmlns:scg="clr-namespace:System.Collections.Generic;assembly=System" xmlns:scg1="clr-namespace:System.Collections.Generic;assembly=System.ServiceModel" xmlns:scg2="clr-namespace:System.Collections.Generic;assembly=System.Core" xmlns:scg3="clr-namespace:System.Collections.Generic;assembly=mscorlib" xmlns:sd="clr-namespace:System.Data;assembly=System.Data" xmlns:sl="clr-namespace:System.Linq;assembly=System.Core" xmlns:st="clr-namespace:System.Text;assembly=mscorlib" xmlns:this="clr-namespace:WorkflowConsoleApplication2;assembly=WorkflowConsoleApplication2" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <this:Workflow1.Implementation> <Sequence sad:XamlDebuggerXmlReader.FileName="e:\myconfig\documents\visual studio 2010\Projects\WorkflowConsoleApplication2\WorkflowConsoleApplication2\Workflow1.xaml"> <WriteLine Text="[myIn]" /> <Assign> <Assign.To> <OutArgument x:TypeArguments="x:String">[myOut]</OutArgument> </Assign.To> <Assign.Value> <InArgument x:TypeArguments="x:String">wxwinter</InArgument> </Assign.Value> </Assign> </Sequence> </this:Workflow1.Implementation> </this:Workflow1> |
并将其作为资源文件存在Dll中,在运行时加载该XAML()
生成的XAML具有Class标记,但并不会生成类,该标记是给VS生成Dll时使用的
这样做的好处是该工作流是强类型
弱类型方式 | Dictionary<string, object> dic = new Dictionary<string, object>(); dic.Add("myIn", "wxd");
var ins = new WorkflowApplication(new Workflow1(), dic); ins.Completed = (p) => { string s = p.Outputs["myOut"].ToString(); System.Console.WriteLine(s); };
ins.Run(); |
强类型方式 | Workflow1 w = new Workflow1(); w.myIn = "wxd"; w.myProperty = "lzm"; //可以对属性赋值
var ins = new WorkflowApplication(w);
ins.Completed = (p) => { string s = p.Outputs["myOut"].ToString(); System.Console.WriteLine(s); };
ins.Run(); |