一 概述
Windows Workflow Foundation(WF)提供承载工作流的若干宿主。WorkflowInvoker提供调用工作流的简单方法,我们使用WorkflowInvoker对象时,就像使用一个普通方法一样创建和启动工作流,并且只能用于不使用持久化的工作流;WorkflowApplication对象为执行工作流提供了更加丰富的模型,包括生命周期事件通知、执行控制、书签恢复和持久化等;WorkflowServiceHost为消息传递活动提供支持,主要用于工作流
二 对象说明
WorkflowInvoker
类名:System.Activities.WorkflowInvoker
程序集:System.Activities.WorkflowInvoker
文件:System.Activities.dll
结构说明:继承自object,是一个sealed类,本身不能被继承.在WF4.0中,可以使用WorkflowInvoker和WorkflowApplication创建并启动工作流实例,但两者在宿主中的线程方式是不一样的。
功能说明:使用WorkflowInvoker启动工作流时,工作流将附加到宿主程序中执行。使用WorkflowApplication启动工作流时,工作流实例将在宿主程序之外的另一线程中运行,使用的是线程池方式。
三 类图
四 功能介绍
此对象的主要功能就是创建和启动工作流,此对象提供了两种方式创建和启动工作流,分别是同步方式和异步方式,同步方式又分为两种方式,静态方法和对象实例直接创建,异步方式也分为两种,InvokeAsync方法和BeginInvoke、EndInvoke方法。下边我们以一个自定义控件为模板来介绍前三种方法。
方法1 通过静态方法同步调用工作流
//非继承自定义控件类,需要继承底层抽象基类 public sealed class resultAndOutArgumentActivity : NativeActivity<int> { //定义两个输入参数,一个输出参数 public InArgument<int> X { get; set; } public InArgument<int> Y { get; set; } public OutArgument<int> myValue { get; set; } //自定义控件默认执行的方法 protected override void Execute(NativeActivityContext context) { //从流程上下文中获取输入参数 int x = X.Get(context); int y = Y.Get(context); //通过计算,将输出参数赋值,并且传入到流程上下文中 context.SetValue(base.Result, x + y); context.SetValue(myValue, x * y); } } static void Main(string[] args) { //定义一个输入参数并且赋值 IDictionary<string, object> dic = new Dictionary<string, object>() { {"X",1}, {"Y",2} }; //定义一个输出参数 IDictionary<string, object> outArgument; // 1 通过静态方法直接调用 int result = System.Activities.WorkflowInvoker.Invoke(new resultAndOutArgumentActivity(), dic, out outArgument, new TimeSpan(0)); Console.WriteLine(result); //打印输出参数 foreach (var item in outArgument) { Console.WriteLine(item); } Console.ReadKey(); }执行结果:
说明:首先,自定义一个非继承类,需要继承NativeActivity<int>类,定义两个输入参数与一个输出参数,重写类的默认执行方法,将两个输入参数从流程执行的上下文中获取出来,将两个参数相加,得到最终输出结果,分别给自定义的输出参数myValue和系统默认输出参数Result赋值,并且将参数以字典形式赋值到流程上下文中。
主方法中,定义一个字典,将两个输入参数分别赋值,然后定义一个输出参数,调用系统静态方法,创建并且启动工作流,此方法返回结果为系统默认返回结果,系统默认获得输出字典中的Result对应的值。显示获取此方法抛出的输出参数,获取字典中的所有参数,打印结果。
方法2 通过实例同步调用工作流
<span style="font-size:18px;"> //非继承自定义控件类,需要继承底层抽象基类 public sealed class resultAndOutArgumentActivity : NativeActivity<int> { //定义两个输入参数,一个输出参数 public InArgument<int> X { get; set; } public InArgument<int> Y { get; set; } public OutArgument<int> myValue { get; set; } //自定义控件默认执行的方法 protected override void Execute(NativeActivityContext context) { //从流程上下文中获取输入参数 int x = X.Get(context); int y = Y.Get(context); //通过计算,将输出参数赋值,并且传入到流程上下文中 context.SetValue(base.Result, x + y); context.SetValue(myValue, x * y); } } static void Main(string[] args) { //定义一个输入参数并且赋值 IDictionary<string, object> dic = new Dictionary<string, object>() { {"X",1}, {"Y",2} }; //定义一个输出参数 IDictionary<string, object> outArgument; // 2 通过宿主实例启动工作流 System.Activities.WorkflowInvoker invoker = new System.Activities.WorkflowInvoker(new resultAndOutArgumentActivity()); outArgument = invoker.Invoke(dic); //打印输出参数 foreach (var item in outArgument) { Console.WriteLine(item); } Console.ReadKey(); }</span>
运行结果:
方法3 通过实例异步调用工作流
//非继承自定义控件类,需要继承底层抽象基类 public sealed class resultAndOutArgumentActivity : NativeActivity<int> { //定义两个输入参数,一个输出参数 public InArgument<int> X { get; set; } public InArgument<int> Y { get; set; } public OutArgument<int> myValue { get; set; } //自定义控件默认执行的方法 protected override void Execute(NativeActivityContext context) { //从流程上下文中获取输入参数 int x = X.Get(context); int y = Y.Get(context); //通过计算,将输出参数赋值,并且传入到流程上下文中 context.SetValue(base.Result, x + y); context.SetValue(myValue, x * y); } } static void Main(string[] args) { //定义一个输入参数并且赋值 IDictionary<string, object> dic = new Dictionary<string, object>() { {"X",1}, {"Y",2} }; // 3 使用InvokeAsync方法与invokeCompleted事件 //实例化流程运行的宿主 System.Activities.WorkflowInvoker myInvoke = new System.Activities.WorkflowInvoker(new resultAndOutArgumentActivity()); //设置流程流转完成时需要执行的方法 myInvoke.InvokeCompleted += testInvoke_InvokeCompleted; //异步调用工作流 myInvoke.InvokeAsync(dic); Console.ReadKey(); } //流程流转完成时需要执行的方法 static void testInvoke_InvokeCompleted(object sender, InvokeCompletedEventArgs e) { //打印输出参数 foreach (var item in e.Outputs) { Console.WriteLine(item); } Console.ReadKey(); }运行结果:
说明:
使用异步方式创建和启动工作流,此案例最终效果和上述示例相同,实现不一样。这里使用了一个委托,当工作流流转完成后,会执行myInvoke.InvokeCompleted 属性后边的委托,我们可以在这个委托中实现我们需要的方法,提示InvokeCompletedEventArgs 包含了我们需要的流程上下文参数。
五 总结:
WorkflowInvoker对象提供并且封装了创建和启动工作流的方法,我们只需要提供简单的参数即可像普通方法一样调用创建和启动,不需要人力去参与,非常的便捷和简单;但是它也有一些缺点,首先它可提供的方法较少,不利于我们创建和控制复杂对象,并且它只能提供不用于持久化的工作流调用方法,因此我们在学习过程中可以使用此对象,工作环境建议使用WorkflowApplication对象,具体的WorkflowApplication使用详解,我们下一篇文章再做介绍。