从 ArgumentException 中获取原始错误消息

Posted

技术标签:

【中文标题】从 ArgumentException 中获取原始错误消息【英文标题】:Getting the original error message out of an ArgumentException 【发布时间】:2021-10-31 17:41:22 【问题描述】:

在.Net 中编写用于内部处理的类时,我经常使用ArgumentException 来表示给定数据有问题,无法处理。由于程序的性质,我在这些异常中输入的文本有时与用户相关,因此它经常显示在 UI 上。

但是,我注意到 ArgumentException 专门覆盖 Message 属性以附加其自己的字符串以指示哪个参数导致异常。我不希望这个额外的文本污染消息,因为实际的参数名称是内部处理信息,实际上不需要向用户显示,而且它添加了一个换行符,而且它是本地化的,一团糟设置我在 UI 上显示的消息的格式。解决这个问题的唯一方法是不给异常提供实际的参数名称,但我也不想通过删除该信息来破坏我自己的调试/日志记录。

当然,我可以使用我自己的异常类,但由于这些方法中有很多是用于压缩和解压缩旧 DOS 游戏中的专有文件格式,我希望这些方法都记录在 wiki 上并且通常其他任何人都可以轻松使用,我更喜欢保持它们的可移植性并避免依赖其他外部类。而且,作为旁注,子类化 ArgumentException 当然会产生同样的问题。

原文出处:

public override String Message

    get 
        String s = base.Message;
        if (!String.IsNullOrEmpty(m_paramName)) 
            String resourceString = Environment.GetResourceString("Arg_ParamName_Name", m_paramName);
            return s + Environment.NewLine + resourceString;
        
        else
            return s;
    

(from referencesource.microsoft.com)

由于这实际上覆盖了Message 属性,因此似乎没有正常的方法可以获取内部存储的真实消息。根据本地化差异(并且我给它的消息可能已经有换行符),在换行符上拆分似乎很混乱并且可能不可靠,并且为此使用反射似乎相当混乱。有没有一种干净的方法来恢复原始消息?

(出于记录原因,在此处发布此解决方案,因为当我遇到这种行为时,我真的很沮丧)

【问题讨论】:

我不明白你对“依赖外部课程”的看法。将ArgumentException 用于 参数或您自己的异常类。 catch(MyOwnException) 有什么问题? 这个问题是我想保持代码的可移植性和易于其他人使用。我在广泛使用ArgumentException 之后才意识到这个问题。 但是用户无论如何都需要你自己的代码,那么为什么不也提供那个额外的类呢?不管怎样:你也可以使用InvalidOperationException 这毫无意义。首先,您依赖于非异常情况的异常,这被视为一种反模式,具体取决于您询问的对象。其次,您“不想使用自己的例外”完全没有意义。只需创建通过简单名称正确识别所发生事件的异常类即可。 “文件包含此函数处理/解压缩的错误数据”如何不是例外情况?这篇文章主要是出于对为什么 .net 标准异常类会破坏程序员放入其中的异常消息的挫败感。 【参考方案1】:

由于我不想深入研究反射,我想了一个在没有相关类行为的情况下获取原始数据的好方法是序列化它。序列化信息中的属性名称非常简单,无需ArgumentException getter 就可以访问它并添加自己的附加信息。

实现这一点的代码非常简单:

public static String RecoverArgExceptionMessage(ArgumentException argex)

    if (argex == null)
        return null;
    SerializationInfo info = new SerializationInfo(typeof(ArgumentException), new FormatterConverter());
    argex.GetObjectData(info, new StreamingContext(StreamingContextStates.Clone));
    return info.GetString("Message");

【讨论】:

以上是关于从 ArgumentException 中获取原始错误消息的主要内容,如果未能解决你的问题,请参考以下文章

尝试实现登录时出现 ArgumentException(ASP.NET Core 项目)

CreateSQLQuery(string) 抛出 System.ArgumentException

获取 ArgumentException:升级到 .NET Core 2.2 后使用 ActionResult<JsonResult>> 作为返回类型的类型参数无效

System.ArgumentException:初始化字符串的格式不符合从索引 0 开始的规范。3

ArgumentException:在字符 xx 处遇到“”,但应为:[]

CreateSQLQuery(string)抛出System.ArgumentException