.net C#:覆写自订例外状况的ToString()方法

k97glaaz  于 2022-11-19  发布在  .NET
关注(0)|答案(8)|浏览(265)

我有一个自定义的异常类,其中包含一些额外的字段。我希望这些字段在ToString()方法中写出,但是如果我实现了自己的ToString(),我会丢失一些其他有用的东西(比如写异常类型名称、内部异常数据和堆栈跟踪)。
对于这样的异常,实现自己的ToString()方法的最佳方式/模式是什么?理想情况下,它应该重用现有的机制,但格式与默认的ToString()实现类似。
UPDATE:将我的自定义字段前置或追加到基本字段中。

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:我已经实现了一个解决方案,下面是我自己的答案。

insrf1ej

insrf1ej1#

这太过分了。您的异常应该覆盖Message属性。

public override String Message {
    get {  
        return base.Message + String.Format(", HttpStatusCode={0}, RequestId='{1}'", 
                    httpStatusCode, 
                    RequestId);
    }
}

Exception类的默认ToString方法基本上是“ClassName: Message --> InnerException.ToString() StackTrace“。因此,覆盖Message会将消息文本准确地放置在它应该放置的位置。

fykwrbwg

fykwrbwg2#

通过查看异常属性,可以手动将默认数据添加到ToString返回的字符串中。例如,下面的代码将模拟异常的ToString方法默认返回的数据(假设没有内部异常):

string.Format("{0}: {1}\r\n{2}", this.GetType().Name, this.Message, this.StackTrace);

或者,您可以简单地将base.ToString返回的数据追加(或预先添加)到要添加的信息中。

llmtgqce

llmtgqce3#

好的,这就是我想到的。我实现了一个扩展类,它复制了格式化异常的原始机制,但有一个转折:一个自定义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);
            });
    }
x3naxklr

x3naxklr4#

您可以覆写ToString()方法以包含您自己的自订信息,并仍会呼叫预设的基底Exception ToString(),如下所示:

public class MyException : Exception
{
    public string CustomField { get; set; }
    public override string ToString()
    {
        return CustomField + Environment.NewLine + base.ToString();
    }
}
uidvcgyl

uidvcgyl5#

如果您主要在调试器中查看它们,则可以使用[DebuggerDisplay]属性指定它们的格式,而不使用现有的ToString方法。
否则,只需重载ToString并确保调用基类版本base.ToString()

rta7y2nd

rta7y2nd6#

最简单的方法

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();
}
eit6fx6z

eit6fx6z7#

在override内调用base.toString()并根据需要修改结果字符串...

5cg8jx4n

5cg8jx4n8#

类似于Glinko's answer的想法,在第一行基字符串后插入变量,实现有点不同:

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)));
}

相关问题