c# - 核心库的异常架构

标签 c# .net exception architecture

我目前正在从事一个项目,该项目分为核心、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);
        }
    }
}

它看起来更好,但在某个时刻每个案例都会有数百个异常。听起来很糟糕。

那么,问题是——在 Core 库中处理异常的最佳方法是什么?也许有任何最佳实践?

附言抱歉我的英语不好,顺便说一句。

最佳答案

一般的做法应该是这样的:

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

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

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

  4. 您可以在您的异常中引入额外的属性,但要注意像 ErrorCode 这样的属性,不要以一个可能有 50 个不同错误代码的通用异常类结束 - 这将是核心库的用户很难处理。您可以在特定错误类型的有限数量的特殊情况下使用诸如 ErrorCode 之类的属性,例如您在执行 GET 请求时获得的 HTTP 代码:200、500、404 和其他一些代码 - 但数量仍然有限。

  5. 应记录核心库中的公共(public)方法和属性,说明它们抛出的异常类型以及何时可以预期这些异常。

关于c# - 核心库的异常架构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27703628/

相关文章:

c# - 有什么方法可以在生成的迭代器 block 中获取对 "this"的引用?

c# - 来自 DatePicker 的可空日期时间值

c# - 在 WPF 中,如何在控件模板中获取命令以绑定(bind)到父项中的属性?

android - 在android中上传文件到Dropbox,putFile方法抛出异常

android - 如何捕获没有互联网异常错误?

java - Android IndexOutOfBoundException

c# - 如何在传输过程中关闭请求流时获取 HTTP 响应

c# - 分层 winform 复选框

c# - 在 C# 中使用 Translate Transform 顺时针和逆时针旋转图像

c# - 为什么 hashset.exceptwith 迭代和检查 !contains 的速度是另一个集合的两倍?