好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

.NET:如何应对边界异常?

.NET:如何应对边界异常?

.NET:如何应对边界异常?

背景

 

为什么语言引入了异常

 

一直没有思考过这个问题,但是异常确实让我的编程生活更快乐,今天早上似乎找到了这个问题的答案:exception之于call stack就像break和continue之于while或for、就像return之于method,总结为一句话:异常只是一种返回机制。

 

为什么异常让程序更简洁

 

代码里只有正常的处理逻辑。

 

  1           ///   <summary> 
  2           ///   创建。
   3           ///   </summary> 
  4           public   ActionResult Create(TAggregateRoot item)
   5           {
   6               this .CurrentCommandService.Execute( new   TCreateCommand
   7               {
   8                  Aggregate =  item
   9               });
  10  
 11               return   this .NewtonsoftJson( new 
 12               {
  13                  success =  true  ,
  14                  items =  this  .GetById(item.Id)
  15               });
  16           }
  17  
 18           ///   <summary> 
 19           ///   修改。
  20           ///   </summary> 
 21           public   ActionResult Update(TAggregateRoot item)
  22           {
  23               this .CurrentCommandService.Execute( new   TUpdateCommand
  24               {
  25                  Aggregate =  item
  26               });
  27  
 28               return   this .NewtonsoftJson( new 
 29               {
  30                  success =  true  ,
  31                  items =  this  .GetById(item.Id)
  32               });
  33          }

 


我的程序代码基本上也是CQRS的,凡是以写为目的的,都是用void进行声明。

 

 

异常的处理

 

异常有五种处理思路,如下图所示:

 

 

关于这五种处理思路的概要介绍可以参考这篇文章: http://HdhCmsTestcnblogs测试数据/happyframework/archive/2013/04/09/3010082.html 。

 

今天的主要目的是介绍“边界异常处理”。

 

边界异常处理

 

当异常到达边界,毫无疑问我们必须进行处理。总体来说,到达边界的异常分为两大类:我们有意抛出的异常和未处理异常,针对这两种异常我们需要不同的处理思路,如:

  有意抛出的异常:不希望写入日志,希望显示到UI。 未处理的异常:希望写入日志,不希望直接显示到UI,希望定制这种异常的显示信息。

 

一个简单的边界异常处理框架

 

结构

 

下图的友好异常就是我们有意抛出的异常或我们能意识到的异常。

 

 

几个核心类型

 

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Threading.Tasks;
   6   using   System.Web.Mvc;
   7  
  8   namespace   Happy.Web.Mvc.ExceptionHanding
   9   {
  10       ///   <summary> 
 11       ///   异常信息提供者接口,如果你希望为异常返回更多的信息,可以实现该接口。
  12       ///   </summary> 
 13       public   interface   IExceptionInformationProvider
  14       {
  15           ///   <summary> 
 16           ///   创建信息。
  17           ///   </summary> 
 18           object   CreateInformation(Exception exception);
  19       }
  20  }

 

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Threading.Tasks;
   6   using   System.Web.Mvc;
   7  
  8   using   Common.Logging;
   9   using   Happy.Web.Mvc.Newtonsoft;
  10  
 11   namespace   Happy.Web.Mvc.ExceptionHanding
  12   {
  13       ///   <summary> 
 14       ///   处理应用程序未捕获的异常。
  15       ///   </summary> 
 16      [AttributeUsage(AttributeTargets.Class, AllowMultiple =  false , Inherited =  true  )]
  17       public   class   WriteExceptionResultAttribute : FilterAttribute, IExceptionFilter
  18       {
  19           ///   <inheritdoc /> 
 20           public   void   OnException(ExceptionContext filterContext)
  21           {
  22               var  exception =  filterContext.Exception;
  23  
 24               this  .LogException(exception);
  25  
 26              filterContext.Result =  ExceptionInformationProviderRegistry.CreateErrorResult(exception);
  27  
 28              filterContext.ExceptionHandled =  true  ;
  29           }
  30  
 31           private   void   LogException(Exception exception)
  32           {
  33               if   (FriendlyExceptionRegistry.Contains(exception.GetType()))
  34               {
  35                   return  ;
  36               }
  37  
 38               LogManager.GetCurrentClassLogger().Error(exception);
  39           }
  40       }
  41  }

 

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Threading.Tasks;
   6   using   System.Web.Mvc;
   7   using   System.Data;
   8  
  9   using   Happy.ExtensionMethod;
  10   using   Happy.DesignByContract;
  11   using   Happy.Web.Mvc.Newtonsoft;
  12  
 13   namespace   Happy.Web.Mvc.ExceptionHanding
  14   {
  15       ///   <summary> 
 16       ///   异常信息提供者注册处。
  17       ///   </summary> 
 18       public   static   class   ExceptionInformationProviderRegistry
  19       {
  20           private   static   readonly  Dictionary<Type, IExceptionInformationProvider>  _providers
  21              =  new  Dictionary<Type, IExceptionInformationProvider> ();
  22  
 23           static   ExceptionInformationProviderRegistry()
  24           {
  25              Register<OptimisticConcurrencyException>( new   Internal.OptimisticConcurrencyExceptionInformationProvider());
  26           }
  27  
 28           ///   <summary> 
 29           ///   注册提供者。
  30           ///   </summary> 
 31           public   static   void  Register<TException> (IExceptionInformationProvider provider)
  32               where   TException : Exception
  33           {
  34              Register( typeof  (TException), provider);
  35           }
  36  
 37           ///   <summary> 
 38           ///   注册提供者。
  39           ///   </summary> 
 40           public   static   void   Register(Type exceptionType, IExceptionInformationProvider provider)
  41           {
  42              exceptionType.MustNotNull( "  exceptionType  "  );
  43              provider.MustNotNull( "  provider  "  );
  44  
 45              _providers[exceptionType] =  provider;
  46           }
  47  
 48           internal   static   ActionResult CreateErrorResult(Exception exception)
  49           {
  50              exception.MustNotNull( "  exception  "  );
  51  
 52               var  exceptionType =  exception.GetType();
  53  
 54               var  information =  CreateDefaultInformation(exception);
  55              
 56               if   (_providers.ContainsKey(exceptionType))
  57               {
  58                   var  extInformation =  _providers[exceptionType].CreateInformation(exception);
  59  
 60                   foreach  ( var  item  in   extInformation.ToDictionary())
  61                   {
  62                      information[item.Key] =  item.Value;
  63                   }
  64               }
  65  
 66               return   new   NewtonsoftJsonResult
  67               {
  68                  Data =  information
  69               };
  70           }
  71  
 72           private   static  Dictionary< string ,  object >  CreateDefaultInformation(Exception exception)
  73           {
  74               return   new  Dictionary< string ,  object > 
 75               { 
  76                  {  "  success  " ,  false   },
  77                  {  "  exception  "  , exception.GetType().Name },
  78                  {  "  message  "  ,exception.Message }
  79               };
  80           }
  81       }
  82  }

 

为乐观并发异常自定义返回消息

 

  1   using   System;
   2   using   System.Collections.Generic;
   3   using   System.Linq;
   4   using   System.Text;
   5   using   System.Threading.Tasks;
   6   using   System.Data;
   7   using   System.Web.Mvc;
   8  
  9   using   Happy.Web.Mvc.Newtonsoft;
  10  
 11   namespace   Happy.Web.Mvc.ExceptionHanding.Internal
  12   {
  13       internal   sealed   class  OptimisticConcurrencyExceptionInformationProvider : ExceptionInformationProvider<OptimisticConcurrencyException>
 14       {
  15           protected   override   object   CreateResult(OptimisticConcurrencyException exception)
  16           {
  17               return   new 
 18               {
  19                  message =  Messages.Error_OptimisticConcurrencyExceptionMessage
  20               };
  21           }
  22       }
  23  }

 

备注

 

像微软的异常处理框架都是一个非常好的东西。

 

合理的利用和使用异常会让程序的结构更加简洁,这些概念只有真正使用了才能深刻的明白。

作者: Leo_wl

    

出处: http://HdhCmsTestcnblogs测试数据/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于.NET:如何应对边界异常?的详细内容...

  阅读:41次