前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >如何在EHAB(EntLib)中定义”细粒度”异常策略?

如何在EHAB(EntLib)中定义”细粒度”异常策略?

作者头像
蒋金楠
发布2018-02-08 13:14:34
5910
发布2018-02-08 13:14:34
举报
文章被收录于专栏:大内老A大内老A

为了解决EntLib的EHAB(Exception Handling Application Block)只能在异常类型级别控制异常处理策略的局限,我在很久之前曾经自定义了一个特殊的异常处理器来提供“细粒度”异常策略的定义(《如何解决EnterLib异常处理框架最大的局限》)。我个人觉得具有一定的实用价值,今天特意对其进行了重构,并将其放到了我在CodePlex上新创建的项目EntLib Extensions

目录 一、完全基于类型的异常策略 二、通过FilterableHandler定义细粒度的异常策略 三、基于“异常筛选”的异常策略 四、异常筛选的匹配优先级

一、完全基于类型的异常策略

EnterLib的异常处理策略基本上可以通过这样的的公式来表示:Exception Policy = Exception Type + Exception Handlers + Post Handling Action,它表达的意思是:“对于某种类型的异常,应该采用哪些Exception Handler去处理,而被处理后的异常还需要采用怎样的后续操作(忽略、抛出处理后异常或者抛出原来捕捉的异常)”。

也就是说,抛出类型的异常类型决定了最终采取的处理策略,这在大部分情况下是可以接受的。但是在很多场景中,不同情况下也可以抛出相同类型的异常,我们期望的行为是:尽管异常类型一样,我们也可以根据具体抛出的异常定义不同的异常处理策略。

一个最为典型的场景就是基于数据库的数据存取,如果你采用的SQL Server,抛出的异常永远只有一种:SqlException。如果完全按照EnterLib EHAB的做法,在任何情况下抛出的SqlException对应的处理方式都是一样的。但是抛出SqlException的情况非常多,比如Server连接断开、认证失败、数据库对象不存在、违反一致性约束等等,如果异常处理框架能够根据最终抛出的异常的具体属性,“智能”地应用相应的策略去处理,这才是我们乐于看到的。

二、通过FilterableHandler定义细粒度的异常策略

为了解决这个问题,我创建了一个特殊的Exception Handler,我将它起名为FilterableHandler。说它特别,是因为FilterableHandler并不从事具体的异常处理操作(比如异常封装、替换、日志等),而是为某个具体的异常类型重新定义了异常处理策略。

由于FilterableHandler本质上就是一个Exception Handler,所以它所提供细粒度异常策略完全定义在基于这个Exception Handler的配置中。为了上读者对“细粒度异常控制”在FilterableHandler德支持有个初步的了解,我们可以来大体了解一下FilterableHandler的配置结构。

代码语言:js
复制
   1: <filters>
   2:    <add name="filter1" type="filterType, assemblyName" .../>
   3:    <add name="filter2" type="filterType, assemblyName" .../>
   4: </filters>
   5: <filterTable>
   6:    <add name="filterEntry1" filter="filter1">
   7:        <exceptionHandlers>
   8:           <add name="handler1" type="exceptionHandlerType, assemblyName" .../>
   9:           <add name="handler2" type="exceptionHandlerType, assemblyName" .../>
  10:           <add name="handler3" type="exceptionHandlerType, assemblyName" ...>
  11:        </exceptionHandlers>
  12:    </add>
  13:    
  14:    <add name="filterEntry2" filter="filter2">
  15:        <exceptionHandlers>
  16:           <add name="handler4" type="exceptionHandlerType, assemblyName" .../>
  17:           <add name="handler5" type="exceptionHandlerType, assemblyName" .../>
  18:           <add name="handler6" type="exceptionHandlerType, assemblyName" .../>
  19:        </exceptionHandlers>
  20:    </add>
  21: </filterTable>

从上面给出的配置中,我们可以大体可以看出:针对某个异常的异常策略被分为两个分支,每个分支分别通过对应着<filterTable>结点下定义的两个“筛选器体条目”(filterEntry1和filterEntry2)。而这两个筛选器表分别适用配置的“异常筛选器”filter1和filter2来判断处理的异常是否满足当前分支的条件。当捕获的异常满足相应的分支的筛选条件,则通过当前分支定义的异常处理器列表(第一个分支:handler1、handler2和handler3,第二个分支:handler4、handler5和handler6)。

三、基于“异常筛选”的异常策略

实际上FilterableHandler提供的“细粒度”异常策略是通过“异常筛选”机制实现的。由于我们需要根据捕获的异常来决定应该采用那个分支对其进行处理,而用于分支判断通过一个特殊的组件——异常筛选器(ExceptionFilter)来实现。我们为异常筛选器定义了如下一个简单的接口,唯一的方法Match用于判断给定的Exception对象是否满足当前异常筛选器的筛选条件。

代码语言:js
复制
   1: public interface IExceptionHandler
   2: {
   3:    bool Match(Exception exception)
   4: }

我们可以通过实现这个接口来自定义我们需要的异常筛选器,比如我们定义了如下一个DomainFilter。该DomainFilter根据Exception对象某个指定的属性值是否和在预先指定的指列表中,进而判断异常是否满足筛选条件。

代码语言:js
复制
   1: public class DomainFilter: IExceptionFilter
   2: {
   3:     public string PropertyName{get; set}
   4:     public string Values{get;set;}
   5:  
   6:     public DomainFilter(string propertyName, string values)
   7:     {
   8:         this.PropertyName = propertyName;
   9:         this.Values = values;
  10:     }
  11:     
  12:     public bool Match(Exception exception)
  13:     {
  14:        var property = exception.GetType().GetProperty(this.PropertyName);
  15:        var value    = property.GetValue(exception, null);
  16:        return this.Values.Split(',').Contains(value.ToString());
  17:     }
  18: }

比如说,现在我们对某种类型的异常进行处理,并且该异常类型具有一个Number属性。现在我们需要针对异常的这个属性来进行分支的选择,比如Number=1、2、和3采用hander1、hander2和handler3进行处理,Number=4、5和6则采用hander4、hander5和handler6进行处理。相应的配置结构如下:

代码语言:js
复制
   1: <filters>
   2:    <add name="domainFilter1" type="DomainFilter,assemblyName" property="Number" values="1,2,3" />
   3:    <add name="domainFilter2" type="DomainFilter, assemblyName" property="Number" values="4,5,6" />
   4: </filters>
   5: <filterTable>
   6:    <add name="filterEntry1" filter="domainFilter1">
   7:        <exceptionHandlers>
   8:           <add name="handler1" type="exceptionHandlerType, assemblyName" .../>
   9:           <add name="handler2" type="exceptionHandlerType, assemblyName" .../>
  10:           <add name="handler3" type="exceptionHandlerType, assemblyName" ...>
  11:        </exceptionHandlers>
  12:    </add>
  13:    
  14:    <add name="filterEntry2" filter="domainFilter2">
  15:        <exceptionHandlers>
  16:           <add name="handler4" type="exceptionHandlerType, assemblyName" .../>
  17:           <add name="handler5" type="exceptionHandlerType, assemblyName" .../>
  18:           <add name="handler6" type="exceptionHandlerType, assemblyName" .../>
  19:        </exceptionHandlers>
  20:    </add>
  21: </filterTable>

四、异常筛选的匹配优先级

实际上,这个“异常筛选”机制是根据WCF 4.0的新特性——路由服务的“消息筛选”机制来设计。路由服务具有一个“匹配优先级”的特性,我依然将其借用过来。对于根据配置的异常筛选器决定的异常处理分支,在某个情况下可以出现这样的情况:处理的异常同时满足多个分支的筛选条件。为此在定义筛选表中的每一个筛选器条目(ExceptionFilterEntry)中除了指定异常筛选器的配置名称外,还具有一个类型为整形的priority属性表示匹配的级别。数字越大,级别越高,只有匹配的级别最高的分支会被选用。

代码语言:js
复制
   1: <filterTable>
   2:   <add name="filterEntry1" filter="filter1" priority="2">
   3:      <exceptionHandlers>...</exceptionHandlers>
   4:   </add>
   5:   <add name="filterEntry2" filter="filter2" priority="1">
   6:      <exceptionHandlers>...</exceptionHandlers>
   7:   </add>
   8:  
   9:   <add name="filterEntry3" filter="filter3" priority="0">
  10:      <exceptionHandlers>...</exceptionHandlers>
  11:   </add>
  12:  
  13: </filterTable>

比如对于上面的配置,如果filterEntry2和filterEntry3都满足匹配条件,那么会选择优先级别最高的filterEntry2(priority="1"),而放弃级别较低的filterEntry1。如果最高级别的匹配分支有多个,则会抛出ConfigurationErrorsException。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2011-09-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、完全基于类型的异常策略
  • 二、通过FilterableHandler定义细粒度的异常策略
  • 三、基于“异常筛选”的异常策略
  • 四、异常筛选的匹配优先级
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档