是否有可能不打破某些例外的执行流程而打破其他例外 - 如果是这样,如何?

时间:2014-06-15 23:53:07

标签: c# exception exception-handling

我需要从外部框架调用几个方法 - 或者我正在编写一个包装器,以便其他用户以非预定的顺序从该框架调用方法。现在,框架的某些方法将抛出异常,即使没有发生“真正的”错误。基本上它们应该是内部异常,只是为了通知那些之前已经执行过的动作。例如:已加载文件。再次加载文件不会有什么坏处,所以我关心这个“错误”根本就没有错误。所以我需要继续这个例外,但我还需要捕捉其他的,真正的异常,例如当连接到客户端和东西的框架不能这样做时。

下面我有一些(非常简化的)示例代码。显然代码不会编译,因为缺少自定义异常的代码。在现实生活中,代码分布在三个程序集中。这意味着,我无法围绕那些仅抛出InternalFrameworkException()的框架方法包装异常处理程序。我只能把它包裹在整个SomeMethod()周围。正如我所写,这是一个极其简化的例子。

有没有办法处理RealException()s但是如果PostSharp没有使用here那么继续InternalFrameworkException()s?请注意,这不是让InternalFrameworkException()失败,但它们实际上根本不会突破try{}块。

namespace ExceptionTest
{
    using System;

    internal class Program
    {
        private static void Main(string[] args)
        {
            try
            {
                SomeMethod();
            }
            catch (InternalFrameworkException exception)
            {
                // Do not actually catch it - but also dont break the
                // execution of "SomeMethod()".
                // Actually I never want to end up here...
            }
            catch (RealException exception)
            {
                // Break the execution of SomeMethod() as usual.
                throw;
            }
            catch (Exception exception)
            {
                // Again, break the execution of SomeMethod() as usual.
                throw;
            }
            finally
            {
                // Clean up.
            }
        }

        #region == Method is actually contained in another assembly referencing this assembly ===

        private static void SomeMethod()
        {
            // Should break if uncommented.
            // MethodThrowingProperException();
            // Should not break.
            MethodThrowingInternalExceptionOrRatherContinuableError();
            // Should execute, even if previously an internal framework error happened.
            MethodNotThrowingException();
        }

        #endregion

        #region ===== Framework methods, they are contained in a foreign dll =====

        private static void MethodThrowingProperException()
        {
            // Something happened which should break execution of the
            // application using the framework
            throw new RealException();
        }

        private static void MethodThrowingInternalExceptionOrRatherContinuableError()
        {
            // Perform some stuff which might lead to a resumable error,
            // or rather an error which should not break the continuation
            // of the application. I.e. initializing a value which is
            // already initialized. The point is to tell the application using
            // this framework that the value is already initialized, but
            // as this wont influence the execution at all. So its rather
            // a notification.
            throw new InternalFrameworkException();
        }

        private static void MethodNotThrowingException()
        {
            // Well, just do some stuff.
        }

        #endregion
    }
}

编辑:我确实在帖子linked above中尝试了这个例子,它只是一个魅力......只在SomeMethod()中使用它。我可以理论上实现这个,因为我在将它们暴露给最终程序集之前包装了SomeMethod()中调用的所有方法,但我不喜欢这种方法,因为它会给我的代码带来无法复杂的复杂性

3 个答案:

答案 0 :(得分:1)

抛出异常时,执行流程中断。您可以捕获异常,但在抛出异常后无法“继续”。

您可以将逻辑分成几部分,然后在抛出异常时继续下一部分。

答案 1 :(得分:0)

在这种情况下,我不确定与AOP方法有什么区别。鉴于您无法更改SomeMethod()或其调用的任何方法,您需要查看如MethodThrowingInternalExceptionOrRatherContinuableError()这样的被调用方法,以及捕获“可持续”异常的方面。

该方面将有效地将方法调用包装在try{...} catch(InternalFrameworkException)(或类似的可捕获异常)块中。

正如您已经指出的那样,即使调用者在catch()块中捕获异常,您也无法在抛出异常后退回到方法中,因此您需要向方法中注入正在调用,像PostSharp这样的AOP框架将允许你这样做。

答案 2 :(得分:0)

我通过在try-catch(InternalFrameworkException)块中包含对InternalFrameworkMethod()的调用并调用someTig(如InternalFrameworkMethodSafe())然后在SomeMethod中调用处理过的InternalFrameworkMethodSafe()来解决类似的问题。

void InternalFrameworkMethodSafe()
{
    try
    {
        InternalFrameworkMethod();
    }
    catch(InternalFrameworkException e)
    {
        Trace.Write("error in internal method" + e);
    }
}

void SomeMethod()
{
    ...
    InternalFrameworkMethodSafe();
    ...
}

如果内部框架处于错误状态且无法继续,则可能无法正常运行。