Reputation: 19004
I have a custom exception class which contains some additional fields. I want these to be written out in the ToString()
method, but if I implement my own ToString()
, I loose some other useful stuff (like writing the exception type name, the inner exception data and the stack trace).
What is the best way/pattern to implement your own ToString()
method for such exceptions? Ideally it should reuse the existing mechanism, but be formatted in way similar to the default ToString()
implementation.
UPDATE: prepending or appending my custom fields to the base.ToString() text isn't ideal IMHO, for example
PimTool.Utilities.OERestServiceUnavailableException: test ---> System.InvalidOperationException: inner message
--- End of inner exception stack trace ---
at PimTool.Tests.Services.OE.OERestClientTests.ExceptionsLogging() in D:\svn\NewPimTool\PimTool.Tests\Services\OE\OERestClientTests.cs:line 178,
StatusCode=0, message='test', requestId='535345'
means the custom fields are written at the end of the (potentially long) exception description. On the other hand, I want the exception type to be the first information written in the description.
UPDATE 2: I've implemented a solution for this, look for my own answer below.
Upvotes: 36
Views: 14824
Reputation: 643
Similar idea to Glinko's answer of insertion of your variables after the first line of base string, a bit different implementation:
public override string ToString()
{
string baseStr = base.ToString();
return baseStr.Insert(baseStr.IndexOf('\n') + 1,
string.Format("HttpStatusCode: {0}, TSError400: {1}\r\n",
(int)HttpStatusCode,
JsonConvert.SerializeObject(TSError400)));
}
Upvotes: 1
Reputation: 21
The simplest way
public override string ToString()
{
StringBuilder sb = new();
var separator = new string[] { Environment.NewLine };
var str = base.ToString().Split(separator, 2, StringSplitOptions.None);
sb.AppendLine(str[0]);
// Your properties
sb.Append(str[1]);
return sb.ToString();
}
Upvotes: 2
Reputation: 18895
This is all overkill. Your exception should just override the Message Property.
public override String Message {
get {
return base.Message + String.Format(", HttpStatusCode={0}, RequestId='{1}'",
httpStatusCode,
RequestId);
}
}
The default ToString method for the Exception class is basically "ClassName: Message --> InnerException.ToString() StackTrace
". So overriding the Message puts your message text exactly where it should be.
Upvotes: 44
Reputation: 19004
OK, this is what I came up with. I've implemented an extension class which replicates the original mechanism for formatting exceptions, but with a twist: a custom Action delegate which provides a plug-in for formatting custom fields:
public static class ExceptionFormatterExtensions
{
public static string ExceptionToString (
this Exception ex,
Action<StringBuilder> customFieldsFormatterAction)
{
StringBuilder description = new StringBuilder();
description.AppendFormat("{0}: {1}", ex.GetType().Name, ex.Message);
if (customFieldsFormatterAction != null)
customFieldsFormatterAction(description);
if (ex.InnerException != null)
{
description.AppendFormat(" ---> {0}", ex.InnerException);
description.AppendFormat(
"{0} --- End of inner exception stack trace ---{0}",
Environment.NewLine);
}
description.Append(ex.StackTrace);
return description.ToString();
}
}
Now you can use this method in your own ToString() implementations without duplicating the formatting code:
public override string ToString()
{
return this.ExceptionToString(
description =>
{
description.AppendFormat(
", HttpStatusCode={0}, RequestId='{1}'",
httpStatusCode,
RequestId);
});
}
Upvotes: 16
Reputation: 50273
You could manually add the default data to the string returned by ToString
, by looking at the exception properties. For example, the following will simulate the data returned by default by a exception's ToString
method (assuming there are no inner exceptions):
string.Format("{0}: {1}\r\n{2}", this.GetType().Name, this.Message, this.StackTrace);
Or, you could simply append (or prepend) the data returned by base.ToString
to the information you want to add.
Upvotes: 14
Reputation: 14551
If you're primarily looking at them in the debugger, then you can use the [DebuggerDisplay]
attribute to specify their formatting and not touch the existing ToString
method.
Otherwise, just overload ToString
and be sure to call the base class version base.ToString()
Upvotes: 5
Reputation: 41872
You can override the ToString() method to include your own custom information, and still call the default base Exception ToString() like this:
public class MyException : Exception
{
public string CustomField { get; set; }
public override string ToString()
{
return CustomField + Environment.NewLine + base.ToString();
}
}
Upvotes: 12
Reputation: 3272
Inside the override call base.ToString() and modify the resulting string to your needs...
Upvotes: 1