核心库的异常体系结构

本文关键字:体系结构 异常 核心 | 更新日期: 2023-09-27 18:35:36

我目前正在做一个分为几个部分的项目,核心,UI等。在很难更改项目架构之前,我想知道在核心库中处理异常的最佳方式是什么?我的意思是,如何组织这些例外?例如,我可以抛出带有有意义消息的系统异常:

// Database implementation within Core library
class Database
{
    void Foo()
    {
        // ...
        if (Something()) 
            throw new InvalidDataException(message:"The something!");
        else
            throw new InvalidDataException(message:"It's not something!");
    }
}    
class UI
{
    void ShowDatabase()
    {
        var database = new Database();
        try
        {
            database.Foo();
        }
        catch (InvalidDataException e)
        {
            CleanUp();
            MessageBox.Show(e.ToString());
        }
    }
}

但是核心库不必以任何方式与用户打交道。我说的对吗?好的,还有另一种方法。我可以抛出带有错误代码的系统异常作为异常消息,以便 UI 层可以为用户本身选择警告消息:

static class ErrorCode
{
   static string Something = "SomethingOccur";
   static string NotSomething = "NotSomethingOccur";
}
class Database
{
    void Foo()
    {
        // ...
        if (Something()) 
            throw new InvalidDataException(message:ErrorCode.Something);
        else
            throw new InvalidDataException(message:ErrorCode.NotSomething);
    }
}    
class UI
{
    void ShowDatabase()
    {
        var database = new Database();
        try
        {
            database.Foo();
        }
        catch (InvalidDataException e)
        {
            if (e.Message == ErrorCode.Something)
            {
                CleanUpSomthing();
                MessageBox.Show(Resources.SomethingMessage);
            }
            else if (e.Message == ErrorCode.NotSomething)
            {
                CleanUpSomethingElse();
                MessageBox.Show(Resources.NotSomethingMessage);
            }
        }
    }
}

现在它更灵活了,但我认为e.Message == ErrorCode.Something看起来很丑。还有第三种方法,分别针对任何情况实现例外:

class SomethingException : Exception
{
    public SomethingException(string message = null, Exception inner = null) : base(message, inner) { }
}
class NotSomethingException : Exception
{
    public NotSomethingException(string message = null, Exception inner = null) : base(message, inner) { }
}
class Database
{
    void Foo()
    {
        // ...
        if (Something()) 
            throw new SomethingException()
        else
            throw new NotSomethingException();
    }
}    
class UI
{
    void ShowDatabase()
    {
        var database = new Database();
        try
        {
            database.Foo();
        }
        catch (SomethingException e)
        {
            CleanUpSomething();
            MessageBox.Show(Resources.SomethingMessage);
        }
        catch (NotSomethingException e)
        {
            CleanUpSomethingElse();
            MessageBox.Show(Resources.SomethingMessage);
        }
    }
}

它看起来更好,但在某个时刻每种情况都会有数百个例外。听起来很糟糕。

所以,问题是 - 处理核心库中异常的最佳方法是什么?也许有任何最佳实践?

附言对不起我的英语,顺便说一句。

核心库的异常体系结构

一般做法应该是这样的:

  1. 可以使用标准 .NET 异常类(例如 ArgumentNullExceptionInvalidOperationException ) 在异常类型与特定情况匹配的任何情况下。有很多 .NET 异常类,您需要了解它们才能知道要抛出哪个类以及何时抛出。

  2. 在与 Core 库的逻辑严格相关的错误的情况下,您可以定义自己的异常类,并使用它们来抛出。

  3. 您可能应该创建一个异常层次结构,其中基本异常类表示一般错误,更具体的异常类继承自它们。例如,您定义的基异常类可能命名为:ex。 CalculationExcepion .然后定义从它继承的类 - 指定特定类型的计算异常。使用这种方法,库的用户将能够捕获基本异常(以涵盖许多错误情况),或根据他们的偏好处理特定异常。

  4. 您可以在异常中引入其他属性,但要小心使用诸如ErrorCode这样的属性,以免最终得到一个可能具有 50 个不同错误代码的通用异常类 - 这对于 Core 库的用户来说很难处理。您可以在特定错误类型的有限数量的特殊情况下使用此类属性ErrorCode,例如执行 GET 请求时获得的 HTTP 代码:200、500、404 和其他一些代码 - 但数量仍然有限。

  5. 应记录 Core 库中的公共方法和属性,说明它们引发的异常类型以及何时会出现这些异常。