1

我想防止引用的库引发的所有异常从我的库中转义。我通过 try catch 过滤所有函数来做到这一点,如果它们不是MyException类型,它会包装异常。我遇到的问题是,在我的 wrap 函数中,如果异常是MyException类型,我最终会丢失原始堆栈跟踪,因为我最终会从新位置重新抛出相同的异常,并且不会嵌入最初抛出的异常,由于堆栈跟踪是从重新抛出异常的新位置记录的,因此原始堆栈跟踪throw会丢失。

public static Exception Wrap(Exception exception)
{
    Exception exceptionToReturn;
    if (exception is MyException)
    {
        exceptionToReturn = exception;
    }
    else
    {
        exceptionToReturn = new MyException("Referenced library exception wrapped", exception);
    }

    return exception;
}

我想要做的是重新抛出与MyException保留原始堆栈跟踪相同类型的异常。但是我不想使用以下MyException代码检查每个孩子:

(exception is ChildOfMyException)
    exceptionToReturn = new ChildOfMyException(exception.Message, exception);

如果我使用泛型。我无法指定显式构造函数。

public static Exception Wrap<TException>(TException exception)
    where TException : Exception, new()
{
    Exception exc;
    if (exception is MyException)
    {
        exc = new TException();
    }
    else
    {
        exc = new MyException("Referenced library exception wrapped", exception);
    }
    return exc;
}

是否有某种我遗漏的方法,或者我必须使用反射来修改 _innerException字段。

4

2 回答 2

3

首先,如果您想重新抛出异常,请使用:

throw;

并不是

throw ex;

最后一条语句将覆盖您的堆栈跟踪,第一条语句将保留它。

您只能在 catch 块内重新抛出异常,而不能在另一个方法内重新抛出异常。你可以尝试这样的事情:

try
{
    // Any code
}
catch(MyException ex)
{
    throw;
}
catch(Exception ex)
{
    throw Wrap(ex);
}

您的Wrap方法仅包装必须包装的异常。本质上它变成了这样:

try
{
    // Any code
}
catch(MyException ex)
{
    throw;
}
catch(Exception ex)
{
    throw new MyException("Referenced library exception wrapped", ex);
}

如果这对您不起作用(因为 try-catch 块会一遍又一遍地重复),您也可以看看 AOP 可能会为您做这件事。使用 postsharp,您的方法可能有点像:

[ExceptionPolicy(bla bla)]
void MyMethod()
{
    // Any code
}

阅读更多:http ://www.postsharp.net/

于 2013-06-17T06:06:25.973 回答
0

如果要保存原始堆栈跟踪并重新抛出原始异常,则必须throw使用throw ex. 因此,您的 wrap 函数需要返回一个布尔值,该布尔值将指示抛出或重新抛出,以及新异常(如果有)。

像这样的东西:

public static bool Wrap(ref Exception exception) {
    if (exception is MyException) {
        // false indicates a rethrow of the original exception
        return false;
    }
    exception = new MyException("Referenced library exception wrapped", exception);
    return true;
}

// Calling code
try {
    // Something
} catch (Exception ex) {
    if (SomeClass.Wrap(ref ex))
        throw ex;
    throw;
}
于 2013-06-17T06:09:27.763 回答