我有一个自定义异常类,其中包含一些其他字段。我想要在ToString()
方法中写出这些,但是如果我实现自己的ToString()
,我会放弃一些其他有用的东西(比如编写异常类型名称,内部异常数据和堆栈跟踪) )。
为此类例外实施您自己的ToString()
方法的最佳方法/模式是什么?理想情况下,它应该重用现有机制,但格式与默认ToString()
实现类似。
更新:将我的自定义字段前置或附加到base.ToString()文本不理想恕我直言,例如
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'
表示自定义字段写在(可能很长)的异常描述的末尾。 另一方面,我希望异常类型是描述中写的第一个信息。
更新2:我已为此实施了解决方案,请在下面查找我自己的答案。
答案 0 :(得分:27)
这太过分了。您的异常应该覆盖Message Property。
public override String Message {
get {
return base.Message + String.Format(", HttpStatusCode={0}, RequestId='{1}'",
httpStatusCode,
RequestId);
}
}
Exception类的默认ToString方法基本上是“ClassName: Message --> InnerException.ToString() StackTrace
”。因此,覆盖消息会将消息文本准确地放在应有的位置。
答案 1 :(得分:12)
您可以通过查看异常属性,手动将默认数据添加到ToString
返回的字符串中。例如,以下将模拟默认情况下由异常ToString
方法返回的数据(假设没有内部异常):
string.Format("{0}: {1}\r\n{2}", this.GetType().Name, this.Message, this.StackTrace);
或者,您只需将base.ToString
返回的数据附加(或预先添加)到您要添加的信息即可。
答案 2 :(得分:11)
好的,这就是我想出来的。我已经实现了一个扩展类,它复制了格式化异常的原始机制,但有一个转折点:一个自定义Action委托,它提供了一个用于格式化自定义字段的插件:
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();
}
}
现在,您可以在自己的ToString()实现中使用此方法,而无需复制格式代码:
public override string ToString()
{
return this.ExceptionToString(
description =>
{
description.AppendFormat(
", HttpStatusCode={0}, RequestId='{1}'",
httpStatusCode,
RequestId);
});
}
答案 3 :(得分:10)
您可以覆盖ToString()方法以包含您自己的自定义信息,并仍然像这样调用默认基础Exception ToString():
public class MyException : Exception
{
public string CustomField { get; set; }
public override string ToString()
{
return CustomField + Environment.NewLine + base.ToString();
}
}
答案 4 :(得分:4)
如果您主要在调试器中查看它们,则可以使用[DebuggerDisplay]
属性指定其格式,而不是触及现有的ToString
方法。
否则,只需重载ToString
并确保调用基类版本base.ToString()
答案 5 :(得分:1)
在覆盖内部调用base.ToString()并根据需要修改生成的字符串......
答案 6 :(得分:0)
最简单的方法
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();
}