`

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

    博客分类:
  • .NET
阅读更多
原帖地址:http://www.cnblogs.com/happyframework/archive/2013/06/07/3123162.html

背景


为什么语言引入了异常


一直没有思考过这个问题,但是异常确实让我的编程生活更快乐,今天早上似乎找到了这个问题的答案: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://www.cnblogs.com/happyframework/archive/2013/04/09/3010082.html


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


边界异常处理


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



  1. 有意抛出的异常:不希望写入日志,希望显示到UI。

  2. 未处理的异常:希望写入日志,不希望直接显示到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 }


备注


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


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


 

本文链接

分享到:
评论

相关推荐

    pCloud.NET:用于pCloud API的.NET包装器

    **pCloud.NET: .NET平台上的pCloud API接口** pCloud.NET是一个专为.NET开发者...通过这个库,开发者可以快速构建出支持云存储功能的应用,实现文件的上传、下载、管理等多种操作,进一步扩展了.NET应用的功能边界。

    .NET异常处理最佳实践

    .NET异常处理是软件开发中的关键环节,特别是在.NET框架下,良好的异常处理机制能确保程序的稳定性和健壮性。以下是一些.NET异常处理的最佳实践: 1. **及早检查问题**:在代码执行的早期阶段就检测潜在的问题,...

    Visual C# .NET 编程经典——从VB6到Visual C# .NET 快速进阶

    - 应用程序域(AppDomain):它是.NET执行环境中的安全边界,可以用于隔离应用程序组件。 - 泛型:引入泛型可以创建类型安全且高效的数据结构,如List和Dictionary, TValue&gt;。 - 异常处理:理解try-catch-finally...

    .NET相关介绍 .NET ;XML Web 服务;环境

    - **背景**:.NET框架的出现是为了应对日益增长的XML Web服务需求,它是在2000年代初互联网爆发式发展背景下诞生的,旨在提供一套统一的开发工具和环境,使开发人员能够更有效地创建基于Web的应用和服务。...

    .NET之美:.NET关键技术深入分析

    3.5.3获得多个返回值与异常处理 3.6订阅者方法超时的处理 3.7委托和方法的异步调用 3.8不使用委托实现Observer模式 3.8.1设计思想概述 3.8.2 Observer模式的接口定义 3.8.3 Observer模式的实现 3.8.4推模式...

    (c#)net面试题(含答案)txt,word文件

    - 应用程序域(AppDomain):理解应用程序域的作用,它是.NET执行代码的安全边界。 - GAC(全局程序集缓存):学习如何存储和共享公共的.NET程序集。 - ADO.NET:掌握数据库连接、数据读取和事务处理,如使用`...

    在ASP.NET 2.0中操作数据之三十八:处理BLL和DAL的异常

    这包括使用参数化查询避免SQL注入、进行数据验证防止无效数据输入、以及在实现功能时考虑边界条件和异常情况等。 总而言之,在*** 2.0中,通过在BLL和DAL层合理使用try-catch结构以及适当配置数据源控件事件,可以...

    深度挖掘.NET Framework 2.0(8):实战.NET Remoting(下)

    3. **序列化和反序列化**:当对象跨越进程或网络边界时,必须将其状态转换为可传输的格式,这个过程称为序列化。到达目的地后,再将数据恢复为原来的对象,即反序列化。.NET框架提供了多种序列化机制,如...

    vb.net 贪吃蛇简单版

    12. **异常处理**:在编程过程中,良好的异常处理可以防止程序因未预见的情况而崩溃,如边界错误、空指针异常等。 通过实现这个简单的贪吃蛇游戏,开发者不仅可以掌握VB.NET的基础语法,还能了解图形用户界面设计、...

    .net高级调试

    通过SOSEX,开发者可以检查和调试GCHandle的状态,确保跨原生/托管边界的正确性。 三、调试工具 2. readme.txt:这份文档通常包含了关于压缩包内资源的使用说明和注意事项。在调试过程中,正确理解和使用这些工具至...

    .net本质论

    3. **异常处理**:CLR提供了统一的异常处理机制,使得异常可以被抛出、捕获并跨方法边界传递。 4. **安全性**:.NET框架提供了一套全面的安全模型,包括代码访问安全(Code Access Security, CAS),确保了代码的...

    VB.NET贪吃蛇游戏

    【VB.NET贪吃蛇游戏】是一款使用微软的Visual Basic .NET编程语言开发的经典小游戏,它基于Windows Forms平台,展示了VB.NET的基本语法、事件处理、图形绘制以及对象编程等核心概念。这款游戏的实现涉及多个关键知识...

    asp.net开发银行交易系统源码

    - **需求分析**:理解银行交易系统的功能需求和业务流程,明确系统边界和预期性能。 - **系统架构**:选择合适的架构模式,如三层架构(表现层、业务逻辑层、数据访问层),利于代码复用和维护。 - **单元测试**...

    VB.NET Remoting 技术手册

    1. 应用程序域(AppDomain):它是.NET Framework中的安全边界,每个AppDomain都是一个独立的执行环境,有自己的内存管理、异常处理和安全策略。 2. 通道(Channel):通道是Remoting中的通信机制,负责在客户端和...

    .net Framework 试卷

    4. .NET框架中的异常处理通过try-catch-finally块实现,try块包含可能引发异常的代码,catch块捕获并处理异常,finally块确保无论是否发生异常都会执行的清理代码。 5. 应用程序域(Application Domain)是.NET ...

    VB.NET Remoting实例

    AppDomain是.NET运行时的一个安全边界,每个应用程序都运行在一个或多个这样的域中。这提供了沙箱环境,使得一个应用程序的故障不会影响到其他应用程序,同时也支持类型隔离和版本控制。 VB.NET Remoting的工作流程...

    .Net分布式企业服务源代码

    6. **错误处理与日志记录**:Chapter 3可能讲解了如何在分布式环境中优雅地处理异常,包括异常传播、事务管理以及详细的日志记录,这对于调试和监控系统状态极其重要。 7. **高性能与优化**:Chapter 11可能涵盖了...

    .Net Remoting系列(5)

    在.NET Remoting中,远程方法抛出的异常会被封装成特殊类型的RemotingException,客户端需要正确处理这些异常以确保程序的健壮性。 通过以上讨论,我们可以看出.NET Remoting在构建五子棋对战游戏中的关键作用,它...

    柴晟版ADO.NET数据库访问技术案例式教程

    Common Language Runtime (CLR) 实现的异常处理机制允许异常跨越过程边界和机器边界。这意味着在.NET中,无论在哪一层级或者哪种语言编写的代码抛出异常,都可以在任何支持.NET的语言中捕获并处理。这为开发者提供...

    vb.net_surfer.rar_Surfer_Surfer VB.net_VB.NET SURFER_vb.net_vb.n

    1. **.NET Framework和VB.NET**: 首先需要了解.NET Framework的基础,包括类库、组件、异常处理、多线程等。VB.NET作为.NET框架的一部分,提供丰富的语法结构,方便编写代码。 2. **COM Interop**: 因为Surfer是...

Global site tag (gtag.js) - Google Analytics