.NET 异常处理的动作策略(Action Policy)

SQL Server 2008基于策略的管理,基于策略的管理(Policy Based Management),使DBA们可以制定管理策略,并将这些策略应用到服务器、数据库以及数据环境中的其他对象上去。基于动作策略(Action Policy)的异常处理使开发人员可以为异常处理制定策略,简单的说,动作策略只是一些可重复使用的一个装饰器,可以很容易应用与方法调用。

异常处理只是一个合乎逻辑的动作策略的一部分,动作策略决定如何对异常做出处理,微软的Enterprise Library的异常处理模块试图为开发人员和policy制定者为整个企业级应用程序各层的异常处理创建一致的策略。但是,异常处理的策略是硬编码的(也就是简单的try-catch代码块)。

如下是简单的示例代码:

try
{
customersDataSet = RunQuery(“GetAllCustomers”);
}
catch(Exception ex)
{
bool rethrow = ExceptionPolicy.HandleException(ex, “Data Access Policy”);
if (rethrow)
throw;
}

红色部分的Exception Policy是硬编码的,这里我给你介绍一种更好的基于动作策略(Action Policy)的异常处理,这个异常处理策略的的原理是充分利用C#的闭包Action<Action>,这个在园子里有很多讨论:

《你不常用的c#之三》:Action 之怪状

利用Reflector把"闭包"看清楚

Action<Action>其实就是一个委托

public delegate void Action();     
public delegate void ActionPolicy(Action action);

很容易我们就可以实现一个出现异常情况下重试3次的策略

void MyRetryPolicy(Action action)     
{      
int counter = 0;      
while (true)      
{      
try      
{      
      action();      
return;      
}      
catch (DbException ex)      
{      
      counter+=1;      
if (counter==3)      
{      
throw;      
}      
Thread.Sleep(1);      
}      
}      
}

这个策略可以这样用

// 没有参数和返回值的简单调用 MyRetryPolicy(() => LongRunningDbCall()); MyRetryPolicy(() => AnotherFragileCall()); // 有一个参数和返回值的调用 int result = 0; MyRetryPolicy(() => result = CreateRecords(records)); 上述代码包含了两部分的逻辑,异常处理和行动策略。这个代码不够通用,可以包装一个行动策略。下面介绍一下在我的项目中使用的行动策略,我使用Autofac模块包装了行动策略,代码如下:

public class ActionPolicyModule : Module   
    {    
        protected override void Load(ContainerBuilder builder)    
        {    
            builder.Register(c => ComposeActionPolicy(c));     
            base.Load(builder);    
        } 
        static ActionPolicy ComposeActionPolicy(IComponentContext context)   
        {    
            ILog log = context.Resolve<ILog>();    
   var actionPolicy = ActionPolicy.With(e => CompositeExceptionHandler(e, log))     
               .Retry(3, (ex,i) =>       
               {    
                   log.DebugFormat(ex, "Retrying exception for the {0} time", i);       
                   SystemUtil.Sleep((0.5 + i).Seconds());  
               });
; 
            return actionPolicy;    
        } 
        static bool CompositeExceptionHandler(Exception ex, ILog log)   
        {    
            ExceptionCounters.Default.Add(ex);
            if (ex.Message.Contains("Password"))   
            {     
                throw new SecuredException(ex);    
            }
            if (ex is DbException)   
            {    
                return true;    
            }
            log.Error(ex, "Unrecoverable exception");   
            return false;    
        }    
    }

我们的方法中对策略的调用的代码很简单

        public void AddAppliction(Application appInfo)   
        {    
            _scopes.Validate(appInfo, "AppInfo", AppRules.Appliction);    
            _log.DebugFormat("AddAppliction()");    
            _policy.Do( () => appRepository.AddAppliction(appInfo));    
        }

_policy就是一个ActionPolicy对象,来自于Autofac内的策略配置,这样我们就可以在我们的代码中去除类似于微软的Enterprise Library的异常处理模块的硬编码代码。细心的你注意到了红色的代码中使用一个Retry Action Policy,出错的时候重试三次,每次之间间隔时间依次加长,重试了三次都不成功才抛出异常,这是一个很有用的功能,比如在数据库发生死锁的时候。动作策略还支持一种断路器,我们的生活中有一种很常见的电路断路器,在发生电涌或过载的时候保护我们的电路,我们的分布式系统中也会碰到类似的现象。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏CDA数据分析师

学会这几招,轻松掌握Python文件管理

一、Python中的文件管理 文件管理是很多应用程序的基本功能和重要组成部分。Python可以使文件管理极其简单,特别是和其它语言相对比。 以下,Peyton ...

3056
来自专栏me的随笔

ASP.NET MVC5 ModelBinder

ASP.NET MVC中,所有的请求最终都会到达某个Controller中的某个Action并由该Action负责具体的处理和响应。为了能够正确处理请求,Act...

1182
来自专栏大内老A

[WCF权限控制]模拟(Impersonation)与委托(Delegation)[上篇]

由于服务操作是在寄宿进程中执行,在默认的情况下,服务操作是否具有足够的权限访问某个资源(比如文件)决定于执行寄宿进程Windows帐号的权限设置,而与作为客户端...

2666
来自专栏linux驱动个人学习

VFS四大对象之二 struct inode

继上一篇文章:https://cloud.tencent.com/developer/article/1053842 二、inode结构体:(转自http://...

5837
来自专栏IMWeb前端团队

上手 yeoman generator

最近折腾脚手架相关的一些事情。说到脚手架,不得不谈的就是yeoman了。 是什么 yeoman是一个脚手架生成工具。 yeoman generator则是yeo...

2365
来自专栏程序员的知识天地

Python实现一个代码行数统计工具

我们经常想要统计项目的代码行数,但是如果想统计功能比较完善可能就不是那么简单了, 今天我们来看一下如何用python来实现一个代码行统计工具。

2111
来自专栏张善友的专栏

Enterprise Library 4 数据访问应用程序块

Enterprise Library 数据访问应用程序块简化了实现常规数据访问功能的开发任务。应用程序可以在各种场景中使用此应用程序块,例如为显示而读取数据、传...

3206
来自专栏葡萄城控件技术团队

Asp.Net MVC4入门指南(2):添加一个控制器

MVC代表: 模型-视图-控制器 。MVC是一个架构良好并且易于测试和易于维护的开发模式。基于MVC模式的应用程序包含: · Models: 表示该应用程序的数...

1987
来自专栏大内老A

ASP.NET Core中如影随形的”依赖注入”[下]: 历数依赖注入的N种玩法

在对ASP.NET Core管道中关于依赖注入的两个核心对象(ServiceCollection和ServiceProvider)有了足够的认识之后,我们将关注...

68710
来自专栏青玉伏案

iOS开发之再探多线程编程:Grand Central Dispatch详解

Swift3.0相关代码已在github上更新。之前关于iOS开发多线程的内容发布过一篇博客,其中介绍了NSThread、操作队列以及GCD,介绍的不够深入。今...

1977

扫码关注云+社区

领取腾讯云代金券