探索工作流(四)--工作流宿主--WorkflowInvoker

        程序中使用工作流可以让我们的程序更加灵活,但是工作流对象不能直接创建和运行,工作流对象的所有创建、启动等操作都是由工作流载体--即工作流宿主来完成,此文即简单介绍下WF4的宿主。

        一 概述

 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启动工作流时,工作流实例将在宿主程序之外的另一线程中运行,使用的是线程池方式。

        三 类图

探索工作流(四)--工作流宿主--WorkflowInvoker_第1张图片

         四 功能介绍

此对象的主要功能就是创建和启动工作流,此对象提供了两种方式创建和启动工作流,分别是同步方式和异步方式,同步方式又分为两种方式,静态方法和对象实例直接创建,异步方式也分为两种,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();

        }
      执行结果:

探索工作流(四)--工作流宿主--WorkflowInvoker_第2张图片


      说明:首先,自定义一个非继承类,需要继承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>

        运行结果:

探索工作流(四)--工作流宿主--WorkflowInvoker_第3张图片


说明:
第二种方式和第一种方式效果一样,只是工作流的创建和启动方式有区别,这里不再描述他们之间的区别。


       方法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();
        }
        运行结果:

探索工作流(四)--工作流宿主--WorkflowInvoker_第4张图片


        说明:
        使用异步方式创建和启动工作流,此案例最终效果和上述示例相同,实现不一样。这里使用了一个委托,当工作流流转完成后,会执行myInvoke.InvokeCompleted 属性后边的委托,我们可以在这个委托中实现我们需要的方法,提示InvokeCompletedEventArgs 包含了我们需要的流程上下文参数。
        五 总结:

        WorkflowInvoker对象提供并且封装了创建和启动工作流的方法,我们只需要提供简单的参数即可像普通方法一样调用创建和启动,不需要人力去参与,非常的便捷和简单;但是它也有一些缺点,首先它可提供的方法较少,不利于我们创建和控制复杂对象,并且它只能提供不用于持久化的工作流调用方法,因此我们在学习过程中可以使用此对象,工作环境建议使用WorkflowApplication对象,具体的WorkflowApplication使用详解,我们下一篇文章再做介绍。

你可能感兴趣的:(workflow,WorkflowInvoker,异步调用工作流)