核心库的例外架构

时间:2014-12-30 10:22:25

标签: 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);
        }
    }
}

它看起来更好,但每个案例在某个时刻会有数百个例外。听起来不错。

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

P.S。对不起我的英语,顺便说一句。

1 个答案:

答案 0 :(得分:7)

一般做法应该是这样的:

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

  2. 在严格连接到Core库逻辑的错误情况下,您可以定义自己的异常类,并使用它们进行抛出。

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

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

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