Creating Custom Exceptions in .NET
来源:互联网 发布:pr视频剪辑软件下载 编辑:程序博客网 时间:2024/04/27 06:34
- Creating Custom Exceptions in .NET
- Part 82 - Creating custom validation attribute in asp.net mvc
- Creating custom objects in JavaScript
- Managing Exceptions in .NET
- Creating Custom Configuration Sections in Web.config Using .NET 2.0's Configuration API
- Creating Custom Configuration Sections in Web.config Using .NET 2.0's Configuration API
- Creating and Deleting Custom Menus in Visio
- Creating Custom Classes in LotusScript, part 1
- Creating Custom Timer Jobs in Sharepoint
- Creating custom data graphics in Visio
- Creating custom and compound views in Android
- Managing Unhandled Exceptions in .NET
- Managing Unhandled Exceptions in .NET
- Creating Web Services In .NET
- Creating Custom Web Controls in C# Stats(转)
- Creating a custom Site Definition in MOSS 2007
- Creating custom and compound Views in Android - Tutorial(翻译)
- Walkthrough: Creating a Custom ASP.NET Web Service
- 常用的ADB命令
- java加密解密
- 读写属性文件
- 关于webservice
- 文档管理的安全性问题
- Creating Custom Exceptions in .NET
- 正则表达式学习指南(一)----入门简介
- Centos 5.7 上LVS+piranha负载均衡及双机热备配置方式
- spring 3.1 mvc 例子浅谈[aop事务](2)
- C++模拟XML解析
- [sql server]存储过程事务
- Jquery iframe 状态监听
- apache通过mod_proxy连接jetty
- 不确定性原理的前世今生 · 数学篇(一)
Creating Custom Exceptions in .NET
Introduction
Minimal Exceptions Types
Serialization Basics
Customizing Serialization
Closing Words
Introduction
Although the .NET framework contains all kinds of exception types which are sufficient in most cases, it can make sense to define custom exceptions in your own applications. They can greatly simplify and improve the error handling and thus increase the overall code quality. Whatever your reasons are for using custom exceptions, this article shows you how to create them and what to pay attention to when it comes to serialization, .NET guidelines and analysis tools.
System or Application?
Any custom exception you create needs to derive from the System.Exception class. You can either derive directly from it or use an intermediate exception likeSystemException or ApplicationException as base class. According to the .NET framework documentation, SystemException is meant only for those exceptions defined by the common language runtime whereas ApplicationException is intended to be used by user code:
So, ApplicationException seems like a good choice as base class for custom exceptions at first. But there has been quite a lot of discussion about this topic and according tothis posting by a Microsoft employee working on .NET, the usage of ApplicationException is no longer recommended. It seems that the current .NET framework and its documentation is already outdated when it comes to the ApplicationException class:
So, the ApplicationException exception class will eventually be deprecated. I therefore let the custom exceptions here in this article derive directly from the Exception class.
Minimal Exceptions Types
The absolute minimum a new custom exception class needs to have is a name. Let’s say you are designing the login mechanism for a database application and as part of this job you need to create a custom exception which is thrown if a login attempt fails. A good name for such an exception would be LoginFailedException. An absolute minimum implementation in C# then looks like:
As you can see, all you need to do to create a basic custom exception is to derive from the Exception class. There’s only one problem with this definition. Since C# unfortunately doesn’t inherit constructors of base classes, this new type only has the standard constructor with no parameters and is therefore relatively useless. So, we need to add at least one constructor which does something useful:
By now we can use our custom exception like most other exceptions. We can throw an instance of LoginFailedException and pass a message which describes the occurred error. But .NET exceptions can do more. You can normally pass a so calledinner exception to one of the constructors which indicates that the created exception is a direct result of a previous one. This inner exception can then be retrieved via the InnerException property. This way you can build entire exceptions chains. Since this can be quite useful sometimes, we extend our existing implementation with this additional constructor:
Looks good so far. We now have a working custom exception which is capable of handling error messages and inner exceptions. Great!
Serialization Basics
Let’s now have a look at what FxCop says to our exception type. In case you don’t know what FxCop is, it’s a nice analysis tool which checks .NET assemblies for conformance to the .NET framework design guidelines. FxCop doesn’t seem to like our exception yet:
Add the following constructor:
Add [Serializable] as this type implements ISerializable
Doesn’t look that great anymore, does it? However, the good news is that this can be fixed quite easily. Both errors deal with the serialization mechanism of .NET in some way. In case you don’t know what serialization is, it’s basically a way to convert an object into a form which can easily be transported or persisted. The counter part to serialization is the deserialization which is responsible for restoring the original object.
Let’s begin with the second error. Any class that is intended to be serializable needs to be marked with theSerializable attribute and since our base class Exception implements the ISerializable interface which is used to customize the serialization process, FxCop wonders why we didn’t add it. So, in order to comply with the serialization guidelines, we simply need to add the Serializable attribute and the second error is already fixed:
Correcting the first error is a bit more tedious. FxCop complains that we forgot to add an additional standard exception constructor. This constructor is used to customize the serialization process of objects. And since the base Exception class defines such a constructor and C# still lacks the support of constructor inheritance, we are better off adding such a beast:
Looks good. FxCop keeps quiet now and we finally have a fully functional exception type which can be used like any predefined exception. It can handle simple error messages and inner exceptions and can even be serialized and deserialized correctly.
Customizing Serialization
Let’s pretend we want to extend our exception by being able to store no only the error message why the login attempt failed, but also which username caused the error. This is pretty straightforward. We just add a new field and a new property to our existing class:
We are now able to set and get the name of the user specified during the login sequence. So far so good, but what about the serialization now? Does it still work as expected, that is, will the username be preserved when being serialized and deserialized? Unfortunately, the answer is ‘no’. You need to take care of it yourself.
Before we extend our exception to do exactly this, I tell you how the customization of the serialization and deserialization works in general. At first, you need to implement the ISerializable interface. This interface contains a single method, named GetObjectData, which is responsible for storing object fields during the serialization process. To do this, you just need to populate a passed SerializationInfo object.
The deserialization process works exactly the other way round. When an object is being deserialized, the previously filled SerializationInfo object is passed to the constructor of your class in which you are responsible for restoring the original object fields. Translated to our example exception, this looks like:
Let’s begin with the serialization. Since our base Exception class already implements the ISerializable interface we can omit it in the list of implemented interfaces and base classes and only need to override and fill the GetObjectData method. At first, we call the GetObjectData method of the base class. This is needed to save the fields common to all exceptions, like the error message, stacktrace information or the inner exception. Then we simply store our username by adding it to the passed SerializationInfo object.
The deserialization works similarly. We just restore our username field in the constructor with the aid of the previously filled SerializationInfo object. To verify that our custom exception works like expected and to demonstrate how an entire serialization and deserialization process looks like, I wrote the following unit test:
During the serialization and deserialization process, the username field is now preserved correctly and thus the Assert class remains silent and the test passes. That this is not the case if we haven’t customized the serialization process can be confirmed quite easily. Simply comment out the GetObjectData method and the call to GetString in the constructor, rerun the test and you’ll see it failing since the UserName property will now return null instead of the correct username.
Closing Words
Aside from the ApplicationException versus Exception discussion, this article has been written with the .NET 1.1 version in mind. However, I don’t expect upcoming versions of the .NET framework to differ (greatly) from the techniques described here in this article, so that the information given here should still be of value in the future. As usual, if you have any comments or questions feel free to contact me attg@gurock.com. Oh, and by the way, you can download the source of the LoginFailedException class and its testhere.