Beginning WF 4.0——翻译(第六章异常处理)

在这一章,你将添加逻辑去验证订单项是否有存货。为了去完成它,你需要重复用同样的方式验证每一个订单项,如果有一项没有存货,你将抛出一个异常,这个异常可以被你的工作流捕获。

重新利用Chapter5项目

打开Visual Studio 2010 创建一个新的项目,选择Blank Solution模板,如图Figure6-1所示。输入解决方案名为Chapter06

复制Chapter05目录下的OrderProcess文件夹到Chapter06的目录下。在Solution Explorer中,右击Chapter06解决方案,选择Add>Existing ProjectAdd Existing Project对话框会出现。选择Chapter06\OrderProcess下的OrderProcess.csproj文件。(这跟上一章的做法是一样的。)

添加检验存货活动

现在你将要添加逻辑去验证是否有充足的存货给订单了。

TryCatch活动

打开OrderWF.xaml文件的设计视图。拖拉一个TryCatch活动到“Handling Charges”活动的下面。修改DisplayNameCheck Stock,点击活动右上角的展开按钮。设计视图如图Figure6-2所示。

TryCatch活动有三个节点。在Try节点中,你可以放置一系列可能产生异常的活动。在Catches节点中,你可以定义一个或多个Catch对象。每一Catch对象处理一个特定的异常。Finally节点是可选的。你可以放置一系列活动到这里,这里的活动是在Try活动(和任何被异常引发的Catch对象)执行完之后执行的。

定义一个异常

你将定义一个异常,这个异常是当没有存货时抛出的。打开Order.cs文件,添加下面的代码去定义OutOfStockException类。

    //----------------------------------------

    //define the exception to be thrown if an item

    //is out of stock

    //----------------------------------------

    public class OutOfStockException : Exception

    {

        public OutOfStockException()

            : base()

        { }

 

        public OutOfStockException(string message)

            : base(message)

        { }

    }

这应该添加在Order类定义之后,在OrderProcess命名空间中。完整的Order.cs如下所示:

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; }

    }

 

    //----------------------------------------

    //define the exception to be thrown if an item

    //is out of stock

    //----------------------------------------

    public class OutOfStockException : Exception

    {

        public OutOfStockException()

            : base()

        { }

 

        public OutOfStockException(string message)

            : base(message)

        { }

    }

}

ForEach活动

拖放一个ForEach活动到Try节点中,设置DisplayNameCheck Each Item。点击展开按钮,在Expression中输入以下代码:

OrderInfo.Items

这定义了循环访问订单项中的每一项。(ForEach活动的详细信息请参考第五章。)在属性窗口中,对于TypeArgument属性,选在Browse for Types,然后选择OrderProcess引用下的OrderItem类。(跟第五章一样)。

If活动

拖拉一个If活动到Body节点,展开活动,设置DisplayNameIf Out of Stock。如图Figure6-3所示。

Condition属性中输入下面代码:

Item.ItemCode = “12346”

提示:在真正的程序开发中,你会从数据库中取出数据,然后验证这些数据是否没有存货。在这个示例中,判断是否没有存货是硬编码的。

Throw活动

拖放一个Throw活动到Then节点。在属性窗口,它只有两个属性:DisplayNameException。对于Exception属性,输入下面代码:

New OrderProcess.OutOfStockException”Item Code: ” + item.ItemCode

这创建了一个OutOfStockException对象,指定了是哪个订单项是没有存货的信息。“If Out of Stock”活动应该如图Figure6-4所示。

Catch活动

Check Stock”活动应该如图Figure6-5所示。

点击Add new catch链接。将会出现一个下拉列表,选择Browse for Types,选择OrderProcess引用下的OutOfStockException,如图Figure6-6所示。

图形应该如图Figure6-7所示。

你将会捕获循环的异常,你应该定义可以执行处理这个异常的活动。对于这个项目,你将输出一行信息去指出是哪一项是没有存货的。拖放一个WriteLine活动到Catches节点中,Text属性为:

 

“Item is out of stock - ” + exception.Message

这行代码从异常中获取信息,信息包含了没有存货的订单项号。收缩“Check Stock”活动然后展开它。“Check Stock”的最终如图Figure6-8所示。

运行程序

点击F5,结果如下所示:

异常

选择在哪里摆放异常处理时非常重要的。例如你可以把整个工作流摆放到一个TryCatch活动的Try节点中,虽然这是一个简单的方式去捕获所有的异常。但是,这可能没有让你真正的去处理这些异常。让我解析一下。

当一个异常被抛出,如果他不是被父活动捕获的,父活动将会流产,而剩下的子活动将会不会被执行。在这个项目中,例如,异常时被If活动的Then分支抛出的。TryCatchForEach活动之外。因为异常没有更早的捕获,当异常到达ForEach活动时,ForEach活动将会停止循环。这意味着一旦异常抛出,工作流将会停止检验其他的订单项。这就是我想说的。

下面的伪代码展示了它是怎么工作的:

Sequence

{

CheckStock (Try)

{

Check Each Item (ForEach)

{

If Out of Stock (If)

{

Throw Exception (Then)

}

}

}

Catch

{

 }

Remaining Activities

}

 

当一个异常抛出,程序会直接去到Catch序列,然后工作流会在Catch这里继续执行下去。这种设计,你可以用来处理费用异常,然而,如果你想继续检验剩下的订单项,你需要把TryCatch活动放到If活动的外面,这会在异常到达ForEach活动之前被处理掉。如下伪代码所示:

Sequence

{

Check Each Item (ForEach)

{

(Try)

{

If Out of Stock (If)

{

Throw Exception (Then)

}

}

Catch

{

}

}

}

 

因为Catch序列在ForEach活动之内,一旦Catch被执行,工作流会接着去处理下一个订单项,如果,你想在异常发生的时候,整个工程要停止,你可以把TryCatch活动放到整个工作流的最顶层,如下所示:

 

(Try)

{

Sequence

{

Check Each Item

{

If Out of Stock

{

Throw Exception

}

}

Remaining Activities

}

}

Catch

{

}

 

因为Catch序列在最外面,在Catch执行完之后,工作流也会完成。

 

第六章源码下载

原文地址:https://www.cnblogs.com/kukafeiso/p/1791776.html