zoukankan      html  css  js  c++  java
  • Beginning WF 4.0翻译——第四章(传递参数)

    在第一章,我已经向你展示了在工作流中怎么使用variables(变量)和arguments(参数)。跟编码类似,variables类似于类成员,而arguments类似于方法的参数。你已经在前三章使用过variables了,在这一章,我将向你展示怎样使用input(输入)、output(输出)arguments(参数)和arguments(参数)是怎么在workflow和宿主程序之间传递。

    创建一个新的解决方案

    创建一个新的Workflow Console Application,如图Figure4-1。命名这个项目为OrderProcess,同时命名这个解决方案为Chapter04

    在这个项目中,你将定义一个货物订单,然后把订单传递到工作流中。工作流将会计算订单的费用,然后把费用返回给应用程序。

    定义订单类

    第一步是定义订单的数据类型。在Solution Explorer(解决方案)中右击项目,选择Add > Class,如图Figure4-2所示。

    Add New Item对话框中(如图Figure4-3),选择Class模板(它应该已经被默认地选择了),指定它的名字为Order.cs,点击Add

    Solution Explorer(解决方案窗口)应该如图Figure4-4所示。

    Order类中输入以下代码:

    using System;

    using System.Collections.Generic;

    using System.Linq;

    using System.Text;

     

    namespace OrderProcess

    {

        public class OrderItem

        {

            public int OrderItemID { get; set; }

            public int Quantity { get; set; }

            public string ItemCode { get; set; }

            public string Description { get; set; }

        }

     

        public class Order

        {

            public Order()

            {

                Items = new List<OrderItem>();

            }

     

            public int OrderID { get; set; }

            public string Description { get; set; }

            public decimal TotalWeight { get; set; }

            public string ShippingMethod { get; set; }

     

            public List<OrderItem> Items { get; set; }

        }

    }

    Order类包含了一些公有成员(OrderIDDescriptionTotalWeightShippingMethod)和一个OrderItem类的集合。工作流会根据这些内容区决定订单的金额。点击F6去生成解决方案。这会编译生成Order类,后面我们需要用到。

    实现工作流

    模板为我们创建了一个工作流文件,名叫Workflow1.xaml。在Solution Explorer中,右击Workflow1.xaml文件,选择Rename(重命名),如图Figure4-5所示。命名为OrderWF.xaml

    你同样要打开OrderWF.xamlcode view。在第一行,修改Class属性为:

    x:Class="OrderProcess.OrderWF"

    定义Arguments

    打开OrderWF.xaml文件(design(设计)视图)。现在定义输入输出arguments。点击工作流设计器的左下角的Argument按钮。设计器将会弹出以下窗口(如图Figure4-6)。

    提示:你可能会想起第一章中定义variables时是需要指定范围的,范围可能是整个工作流或者是特定的一个活动(和他的子活动)。对于arguments,然而,是不需要定义范围的,因为它已经被默认的指定为对整个工作流有效,因为它是指定来传入传出数据到工作流的。因此,当定义argument是是没有Scope属性的。

    点击Create Argument链接。输入NameOrderInfoDirectionIn。点击ArgumentType,将会弹出一个下拉菜单,如图Figure4-7所示。

    选择最后一条(Browse for Types)。这时会弹出一个对话框,如图Figure4-8所示。

    展开OrderProcess引用,选择Order类,点击OK

    提示:如果在OrderProcess引用中看不见Order类,你必须生成解决方案。点击Cancel按钮,点击F6生成解决方案(这时有可能报错“The type or namespace name ‘Workflow1’ could not be found (are you missing a using directive or an assembly reference?)”)

    ,然后就可以设置Argument类型了。

    再次点击Create Argument链接,创建另外一个argument。输入NameTotalAmountDirectionOutArgumentTypeDecimalDecimal类型不再下拉列表中,你需要导航到这个类型(正如第一个argument定义那样)。Decimal类型可以在mscorlib引用的System命名空间中找到。

    提示:你不必通过浏览引用和命名空间来找你需要的类型。你可以直接在对话框的最上面输入类型的命名空间和类型。例如,需要Decimal类型,只是需要输入System.Decimal。实际上,你甚至不需要输入特定的命名空间,你只要输入Decimal,之后下面就会出现匹配的类型。

    设计工作流

    现在你可以设计活动来处理传进来的订单了。首先拖拉一个Sequence活动到工作流设计器上,然后拖放一个WriteLine活动到Sequence中。设置Text属性为“Order Received”。拖放一个Assign活动到WriteLine活动的下面。设置DisplayNameInitialize TotalTo属性为TotalAmountValue属性为0Assign的属性窗口如图Figure4-9所示。

    这个活动简单的把TotalAmount初始化为0

    Switch活动

    Switch活动的工作原理跟C#中的switch类似。它允许你执行一系列的活动根据表达式的值。你将会使用Switch活动去验证ShippingMethod而去决定收费。在Toolbox中,Switch活动显示为Switch<T>。这意味着他是一个模板类和他可以操作不同的数据类型。拖放一个Switch活动到Assign活动的下面。你应该可以看到弹出了一个对话框,如图Figure4-10所示,这个对话框要求你指定数据类型。ShippingMethod是一个string类型,因此选择String类型。

    点击OK。在属性窗口中,设置DisplayNameHandling ChargesHandling Charges活动应该如图Figure4-11所示。

    Switch活动有一个Expression属性,一个default分支,和一些用户定义的分支。输入expressionOrderInfo.ShippingMethod。点击Add new case链接(在活动的底部)。输入case的值为NextDay。再次点击Add new case,输入case2ndDay。这时活动如图Figure4-12所示。

    设计器显示了所有的case(分支),和其中一个分支是展开的,以便你可以看到这个分支中有哪些活动。你可以点击Add an activity链接展开一个收缩的分支。

    Expression活动

    到目前为止,你已经定义了NextDay2ndDay分支到Switch活动中,default分支是用来当ShippingMethod不是其中一个分支的值时来执行的。现在你需要指定每一个分支要执行的活动。对于这个项目,你将使用Add活动。

    提示:在System.Activities.Expressions命名空间中包含了很多工作流活动。包括AddSubtractMultiplyDivide活动。它也包括EqualGreaterThanAndOr活动,你可以直接在你的工作流中使用它们。

    不幸运的是,Add活动不能在toolbox中,你需要直接在.xaml代码中输入这个活动。保存项目。在Solution Explorer中右击OrderWF.xaml,选择View Code。它会弹出一个窗口询问你是否关闭现有窗口,点击YesSwitch活动定义如下:

        <Switch x:TypeArguments="x:String" DisplayName="Handling Charges" Expression="[OrderInfo.ShippingMethod]" sap:VirtualizedContainerService.HintSize="481,260">

          <x:Null x:Key="NextDay" />

          <x:Null x:Key="2ndDay" />

        </Switch>

    注意到NextDay2ndDay分支的属性x:Null,这表明这个分支没有包含活动,用以下代码覆盖这两行代码:

    <Add x:TypeArguments="x:Decimal, x:Decimal, x:Decimal" x:Key="NextDay" sap:VirtualizedContainerService.HintSize="461,100" Left="[TotalAmount]" Result="[TotalAmount]" Right="[15]" />

          <Add x:TypeArguments="x:Decimal, x:Decimal, x:Decimal" x:Key="2ndDay" sap:VirtualizedContainerService.HintSize="461,100" Left="[TotalAmount]" Result="[TotalAmount]" Right="[10]" />

     

    在上面代码之前加上:

          <Switch.Default>

            <Add x:TypeArguments="x:Decimal, x:Decimal, x:Decimal" sap:VirtualizedContainerService.HintSize="463,100" Left="[TotalAmount]" Result="[TotalAmount]" Right="[5]" />

          </Switch.Default>

    注意:以上代码跟原文有不一致,因为我试过原文的方法会报错,所以我直接把Add活动添加到toolbox中,然后拖放到相应的分支中,上面的代码是自动生成的。

    Add活动有三个属性:LeftRightResultRight的值加上Left的值然后赋值给Result属性,LeftResult属性设置为TotalAmount参数,Right属性被指定为一个常数。

    Switch活动的完整定义如下:

        <Switch x:TypeArguments="x:String" DisplayName="Handling Charges" Expression="[OrderInfo.ShippingMethod]" sap:VirtualizedContainerService.HintSize="481,258">

          <Switch.Default>

            <Add x:TypeArguments="x:Decimal, x:Decimal, x:Decimal" sap:VirtualizedContainerService.HintSize="463,100" Left="[TotalAmount]" Result="[TotalAmount]" Right="[5]" />

          </Switch.Default>

          <Add x:TypeArguments="x:Decimal, x:Decimal, x:Decimal" x:Key="NextDay" sap:VirtualizedContainerService.HintSize="461,100" Left="[TotalAmount]" Result="[TotalAmount]" Right="[15]" />

          <Add x:TypeArguments="x:Decimal, x:Decimal, x:Decimal" x:Key="2ndDay" sap:VirtualizedContainerService.HintSize="461,100" Left="[TotalAmount]" Result="[TotalAmount]" Right="[10]" />

        </Switch>

    保存项目,右击OrderWF.xaml文件,选择View DesignerSwitch活动如图Figure4-13所示。

    ShippingMethodNextDay是,TotalAmount将会增加15$;当为2ndDay是,将增加10$。当为其他值时,将增加5$。如果你点击其中的一个switch分支,你将看到分支中包含什么活动,如图Figure4-14所示。

    点击Add活动,它的属性将在属性窗口出现(如图Figure4-15所示),如果需要,你可以在这里直接修改它的属性。

    拖放另外一个Assign活动到Switch活动的下面,DisplayNameFreight ChargesTo属性为TotalAmountValue属性为:

    TotalAmount + (OrderInfo.TotalWeight * 0.50D)

    拖放一个WriteLine活动到“Freight Charges”活动的下面,设置Text属性为:

    “That Total amount is: $” + TotalAmount.ToString()

    这展示了订单的总金额。最后的工作流图应该如图Figure4-16所示。

    引用工作流

    在这个项目,控制台程序自动的引用了工作流,用下面代码覆盖Program.cs

    using System;

    using System.Linq;

    using System.Activities;

    using System.Activities.Statements;

    using System.Collections.Generic;

     

    namespace OrderProcess

    {

     

        class Program

        {

            static void Main(string[] args)

            {

                Order myOrder = new Order()

                {

                    OrderID = 1,

                    Description = "Need some stuff",

                    ShippingMethod = "2ndDay",

                    TotalWeight = 100

                };

     

                IDictionary<string, object> input = new Dictionary<string, object>

                {

                    {"OrderInfo", myOrder}

                };

     

                //execute the workflow

                IDictionary<string,object> output = WorkflowInvoker.Invoke(new OrderWF(), input);

     

                //Get the TotalAmount returned by workflow

                decimal total = (decimal)output["TotalAmount"];

                Console.WriteLine("Workflow return ${0} for my order total", total);

     

                Console.WriteLine("Press ENTER to exit");

                Console.ReadLine();

            }

        }

    }

     

    首先创建了一个Order对象,在Order对象中定义了测试的数据。然后创建了一个Dictionary对象,用来存储Order对象。调用了WorkflowInvoker类的静态方法Invoke(),在Invoke()方法中传递了Dictionary对象。Invoke()方法创建和执行一个工作流实例在应用程序的线程中。

    Dictionary中传递数据是可以同时传多个参数的。这是非常重要的去匹配dictionarykey和工作流中的传入参数,而且dictionary中对象的类型也要与工作流中传入参数匹配。

    Invoke()方法返回一个Dictionary对象,这个dictionary对象包含了工作流的所有传出和传出/传入参数。

    运行程序

    点击F5运行程序,结果应该如下所示:

    为了去验证结果是否正确,你可以手动的去计算一下。ShippingMethod2ndDay,这代表要加上$10TotalWeight100,价格为$0.50一磅,这就是一共$50。加上前面的$10就是$60

     

    第四章源码下载

  • 相关阅读:
    python之各种包
    正则表达式
    import/模块的导入
    迭代器/可迭代对象/生成器
    Day2 列表list
    Day1 字符串格式化
    Day1 字符编码及编码函数
    Python 学习笔记 之 随着学习不断更新的Python特性搜集
    Day1 input&print
    Newtonsoft.Json日期转换
  • 原文地址:https://www.cnblogs.com/kukafeiso/p/1760048.html
Copyright © 2011-2022 走看看