Подтвердить что ты не робот

С#: переопределение метода ToString() для пользовательских исключений

У меня есть специальный класс исключений, который содержит некоторые дополнительные поля. Я хочу, чтобы они были записаны в методе ToString(), но если я реализую свой собственный ToString(), я теряю некоторые другие полезные вещи (например, записывая имя типа исключения, внутренние данные исключения и трассировку стека).

Каков наилучший способ/шаблон для реализации собственного метода ToString() для таких исключений? В идеале он должен повторно использовать существующий механизм, но быть отформатирован таким же образом, как и стандартная реализация ToString().

UPDATE: добавление или добавление моих настраиваемых полей в base.ToString() текст не является идеальным IMHO, например

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: я применил для этого решение, найдите свой ответ ниже.

4b9b3361

Ответ 1

Хорошо, вот что я придумал. Я реализовал класс расширения, который реплицирует исходный механизм форматирования исключений, но с твист: пользовательский делегат 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);
            });
    }

Ответ 2

Это все излишество. Ваше исключение должно просто переопределить свойство сообщения.

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

Метод ToString по умолчанию для класса Exception в основном "ClassName: Message --> InnerException.ToString() StackTrace". Поэтому переопределение сообщения помещает текст вашего сообщения точно там, где оно должно быть.

Ответ 3

Вы можете вручную добавить данные по умолчанию в строку, возвращаемую ToString, просмотрев свойства исключений. Например, следующее будет имитировать данные, возвращаемые по умолчанию методом исключений ToString (при условии отсутствия внутренних исключений):

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

Или вы можете просто добавить (или добавить) данные, возвращаемые base.ToString, к информации, которую вы хотите добавить.

Ответ 4

Вы можете переопределить метод ToString(), чтобы включить свою собственную пользовательскую информацию, и по-прежнему вызывать базовую версию Exception ToString() по умолчанию:

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

Ответ 5

Если вы в основном смотрите на них в отладчике, вы можете использовать атрибут [DebuggerDisplay], чтобы указать их форматирование и не касаться существующего метода ToString.

В противном случае просто перегрузите ToString и обязательно вызовите версию базового класса base.ToString()

Ответ 6

Внутри переопределить вызов base.ToString() и изменить результирующую строку на ваши нужды...