.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,这个在园子里有很多讨论:

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

利用Reflector把"闭包"看清楚

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,出错的时候重试三次,每次之间间隔时间依次加长,重试了三次都不成功才抛出异常,这是一个很有用的功能,比如在数据库发生死锁的时候。动作策略还支持一种断路器,我们的生活中有一种很常见的电路断路器,在发生电涌或过载的时候保护我们的电路,我们的分布式系统中也会碰到类似的现象。

本文来自云栖社区合作伙伴“doNET跨平台”,了解相关信息可以关注“opendotnet”微信公众号

目录
相关文章
|
6月前
|
Java
已解决Java.net.MalformedURLException异常的有效方法java.net.MalformedURLException: no protocol异常处理
已解决Java.net.MalformedURLException异常的有效方法java.net.MalformedURLException: no protocol异常处理
353 0
|
XML 数据采集 开发框架
asp.net core添加全局异常处理及log4net、Nlog应用
文章来源于阿里云 MVP郭联钰。
509 0
|
Web App开发 前端开发 .NET
ASP.NET MVC-异常处理&自定义错误页
原文:ASP.NET MVC-异常处理&自定义错误页 一、应用场景  对于B/S应用程序,在部署到正式环境运行的过程中,很有可能出现一些在前期测试过程中没有发现的一些异常或者错误,或者说只有在特定条件满足时才会发生的一些异常,对于使用ASP.
1095 0