捕获/修改(消息)/ Rethrow相同类型的异常

And*_*iff 7 c# casting exception throw

我想要一个中心位置从异常中提取信息,将我需要的所有信息设置为其消息参数,然后将该信息重新抛出为相同类型的异常.

更好的解决方案可能是在最终处理异常的地方执行此操作(并记录其消息),但是..我可以控制抛出异常的地方,而不是接收异常的地方记录其消息内容.

除了那个设计决定,并且假设message是一个readonly属性,我会(?)以某种方式创建一个新的Exception对象,有没有办法让新的异常对象与原始异常对象相同?

这是我的代码,它不编译 - 它偶然发现了抛出线(我尝试动态转换对象).

public static void RethrowExceptionWithFullDetailInMessage(string msg, Exception ex)
{
    Exception curEx = ex;
    int cnt = 0;
    while (curEx != null)
    {
        msg += "\r\n";
        msg += cnt++ + " ex.message: " + curEx.Message + "\r\n";
        msg += "Stack: " + curEx.StackTrace;
        curEx = curEx.InnerException;
    }
    object newEx = Convert.ChangeType(new Exception(msg), ex.GetType());
    throw (ex.GetType())newEx;
}
Run Code Online (Sandbox Code Playgroud)

做这个

throw (Exception)newEx;
Run Code Online (Sandbox Code Playgroud)

保留类型?(它汇编.)

Convert.ChangeType是否确保我得到了正确类型的异常?

iam*_*lin 11

你在这里想要做的并不像看起来那么容易,而且还有很多陷阱需要考虑.

请记住,Convert.ChangeType()会将一种类型转换为另一种类型(假设存在这样的路径,例如将字符串转换为int).大多数例外不会这样做(为什么会这样?)

为了解决此问题,您必须使用GetType()方法在运行时检查异常类型,并找到具有您可以满足的要求并调用它的构造函数.这里要小心,因为您无法控制如何定义所有异常,因此无法保证您可以访问"标准"构造函数.

话虽这么说,如果你觉得自己是一个规则破坏者,你可以做这样的事......

void Main()
{
    try
    {   
        throw new Exception("Bar");
    }
    catch(Exception ex)
    {
        //I spit on the rules and change the message anyway
        ex.GetType().GetField("_message", BindingFlags.Instance | BindingFlags.NonPublic).SetValue(ex, "Foo");
        throw ex;
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

可能有点晚了,但这对你有用吗?

catch (Exception ex)
{
    throw new Exception("New message", ex);
}
Run Code Online (Sandbox Code Playgroud)

  • 这种方法的问题是,如果您捕获特定的异常,例如“System.ArgumentException”,您将重新抛出“System.Exception”类型的一般异常。如果您在调用链的顶部有代码希望捕获特定的异常,那么它就不会捕获。我只是因为我自己的代码像你的例子一样编写而犯了这个错误! (3认同)