【问题标题】:One Exception handler for all exceptions of a CLASS一个 CLASS 的所有异常的异常处理程序
【发布时间】:2009-08-03 11:23:52
【问题描述】:

我有一个包含许多方法的类,并希望为所有方法提供一个异常处理程序。 这些方法太多了,而且它们有不同的参数,如果为每个方法编写 try/catch 会很丑。

您是否知道一种方法,我可以通过在类异常处理程序中处理它们来做到这一点。

更新:


很多人问我为什么。原因是我正在使用各种方法调用数据源。 所以我的班级有函数getData1,gedData2,getData3,getData4,......,getDataN。问题是没有办法检查连接是否仍然打开并且创建新连接非常昂贵。所以我试图重用连接,如果下一次通话的连接失败,我会抓住这个并重新连接并重试。这就是为什么我需要这个 try/catch all 块。

为所有功能执行此操作:

try{    
   datasource.getData()
}
catch(ConnectionException)
{
   datasource.Connect();
   datasource.getData()
}

谢谢

【问题讨论】:

  • 我知道这是一个老问题,但我想说的是,虽然我大多同意以下在提问当天提交的回复,但有时这种能力会非常有用. husayt 在上面描述了一个,我发现了这个问题,因为我有另一种情况。尽管杰克艾伦的回答不适用于我的场景,但我还是赞成它,因为它在其他情况下很有用,而且非常聪明,恕我直言。也就是说,在您使用 Jack 的“解决方案”之前,请确保没有其他方式来构建您的代码来完全避免这种需要。
  • 没有这样的机制——也不应该有,恕我直言。它与控制流的传递方式不一致。你要做的是“丑陋”,这并不重要。您所做的解决方案并不重要,需要编写额外的代码。重要的是,当您(或其他人)忘记原始细节时,您能够编写易于理解并在以后维护的软件。如果一个方法在异常发生时需要做某事,那么方法中必须有一些东西,说明要做什么。这是一件好事。
  • 顺便说一句,我赞成这个问题,因为我认为这是一个很好的问题。想要这样做是合法的,对其他人有用。了解为什么没有办法做到这一点,并了解应该做什么(在你的问题中你已经做过,即使你不喜欢结果),对其他人有用。
  • 2017年也是这样吗?

标签: c# exception


【解决方案1】:

您可以使用委托将方法的代码传递到单个 try catch 中,如下例所示:

    private void GlobalTryCatch(Action action)
    {
        try
        {
            action.Invoke();
        }
        catch (ExpectedException1 e)
        {
            throw MyCustomException("Something bad happened", e);
        }
        catch (ExpectedException2 e)
        {
            throw MyCustomException("Something really bad happened", e);
        }
    }

    public void DoSomething()
    {
        GlobalTryCatch(() =>
        {
            // Method code goes here
        });
    }

【讨论】:

  • 非常好。如果方法应该返回一个对象会是什么样子?
  • @Rune 只需在调用GlobalTryCatch 之前声明一个变量,并将结果分配给大括号中的这个变量。
【解决方案2】:

我不知道为什么您可以从使用单一方法处理类中的所有异常中受益(您能详细说明一下吗?我很好奇...)

无论如何,您可以使用AOP(面向方面​​编程)技术在类的方法周围注入(静态或在运行时)异常处理代码。

有一个很好的程序集后处理库PostSharp,您可以使用类中方法的属性对其进行配置:

您可以定义这样的方面(来自 PostSharp 网站):

public class ExceptionDialogAttribute : OnExceptionAspect
{
    public override void OnException(MethodExecutionEventArgs eventArgs)
    {
        string message = eventArgs.Exception.Message;
        MessageBox.Show(message, "Exception");
        eventArgs.FlowBehavior = FlowBehavior.Continue;
    }
}

然后你将属性应用到你想要监视异常的方法上, 像这样:

public class YourClass {

    // ...

    [ExceptionDialog]
    public string DoSomething(int param) {
        // ...
    }
}

你也可以将属性应用到整个类,像这样:

[ExceptionDialog]
public class YourClass {
    // ...
    public string DoSomething(int param) {
        // ...
    }
    public string DoSomethingElse(int param) {
        // ...
    }
}

这会将通知(异常处理代码)应用于类中的每个方法。

【讨论】:

  • 好答案。仅供参考,看起来 PostSharp 将虚拟方法的 OnException 签名更改为 OnException(MethodExecutionArgs eventArgs)。
  • 我只是想为此添加我的用例,我正在为游戏创建一个模组。如果抛出我没有捕捉到的异常,我希望我的 mod 自行注销并记录错误(而不是让游戏崩溃)。所以这很方便。
【解决方案3】:

异常与类无关,而是面向方法/调用堆栈。一般来说,一个对象不应该尝试处理来自它自己的方法的异常。这取决于这些方法的调用者。

【讨论】:

    【解决方案4】:

    我认为没有。您可以将 try/catch 移至调用者,但这不是很好的设计。最好将其分离到另一个类中,并使用反射来调用方法,如下所示:

    public class MyClass {}
    public class MySafeClass {
        public void CallMethod(string name, object[] param) {
            Type t = typeof(MyClass);
            MyClass mc = new MyClass();
            try {
                t.GetMethod(name).Invoke(mc, param);
            }
            catch {
                //...;
            }
        }
    

    }

    但你不应该这样做!这不是很好的做法。

    另一种方法仍在使用try/catch,但只有一个方法可以向用户抛出异常等:

    public class MyClass {
        void DoException(string message) {
            throw new Exception(message);
        }
    }
    

    但那仍然不是一个好的选择。

    我不明白为什么它会很丑 - 即使您只是将整个方法包装在一个 try/catch 中并带有一条消息。这可能是可行的。

    将它们留下并将它们传回给调用者也是一个更好的选择,也许在try/finally

    尝试/捕捉所有内容并不难,尤其是使用 Visual Studio 和 SharpDevelop 中的 sn-ps。

    【讨论】:

    • 感谢您的回复。也许查看问题的更新,您会看到我的原因。
    【解决方案5】:

    这听起来像是您的设计有问题。您能否详细说明您要捕获哪些异常以及原因,我们可以尝试并提供帮助。

    【讨论】:

    • 是的,可能我需要提供更多上下文,请检查我对问题的更新。
    【解决方案6】:

    你可能想对你的 main 方法添加一个 try/catch,尽管我认为这是对异常处理的严重滥用,除非你想附加一个记录器或某事。

    【讨论】:

    • 我只需要该类的东西并在该类中处理Thnks
    猜你喜欢
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 2012-03-04
    • 2021-06-29
    • 1970-01-01
    相关资源
    最近更新 更多