When writing classes for internal processing in .Net, I often use ArgumentException
to indicate something is wrong with the given data and it can't be processed. Due to the nature of the program, the text I put in these exceptions is sometimes relevant to the user, and so it often gets shown on the UI.
However, I noticed that ArgumentException
specifically overrides the Message
property to append its own string to indicate which argument caused the exception. I don't want this extra text polluting the message, since the actual argument name is internal processing info that really doesn't need to be shown to the user, and the fact it adds a line break, and that it is localised, messes up the formatting of the message I show on the UI. The only way to get around this is to not give the exception the actual argument name, but I don't want to sabotage my own debugging / logging by removing that information, either.
I could use my own exception class, of course, but since a lot of these methods are for compression and decompression of proprietary file formats in old DOS games, and I want these methods to both be documented on a wiki and be generally easily usable by anyone else, I'd prefer keeping them portable and avoid reliance on other external classes. And, as a side note, subclassing ArgumentException
would of course give the same issue.
The original source:
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)
Since this actually overrides the Message
property, there seems to be no normal way to get to the real message that's stored internally. Splitting on a line break seems messy and potentially unreliable depending on localisation differences (and the message I give it might potentially have line breaks already), and using reflection for this seems rather messy. Is there a clean way to recover the original message?
(Posting this here with solution for documenting reasons, since this behaviour really frustrated me when I encountered it)
Since I didn't want to dig into reflection, I figured a good way to get the original data without the associated class behaviour would be to serialize it. The names of the properties in the serialised info are very straightforward, and can be accessed without the ArgumentException
getter mangling it with its own additions.
The code to accomplish this turned out to be pretty straightforward:
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");
}