[FeatureRequest] [Review] FormatterException
От: rameel https://github.com/rsdn/CodeJam
Дата: 10.03.17 11:43
Оценка: 9 (1)
У меня есть давно написанный класс FormatterException, я говорил о нем вот тут: Re[5]: 2IT: Предложения по свежим сбросам
Автор: rameel
Дата: 04.05.16
. Решил все-таки его причесать и переписать с использованием SerializationInfo. Стоит заменить текущую реализцию в проекте? Умеет понимать вложенные исключения и в целом печатает исключения в более наглядной форме.

  FormatException
        private static void FormatExceptionImpl([NotNull] IndentedTextWriter writer, [NotNull] Exception exception, bool captureStackTrace)
        {
            var separatorIndex = exception.Message.IndexOfAny(_separator);
            if (separatorIndex == -1)
            {
                writer.WriteLine("{0}: {1}", exception.GetType().FullName, exception.Message);
            }
            else
            {
                writer.WriteLine("{0}: {1}", exception.GetType().FullName, exception.Message.Substring(0, separatorIndex));
                WriteText(writer, nameof(Exception.Message), exception.Message);
            }

            var info = new SerializationInfo(exception.GetType(), new FormatterConverter());
            exception.GetObjectData(info, new StreamingContext());

            IReadOnlyCollection<Exception> exceptions = null;

            foreach (var se in info)
            {
                if (se.Name == nameof(Exception.Message) || se.Name == "ClassName")
                    continue;

                if (se.Value is IEnumerable<Exception> e)
                {
                    exceptions = e as IReadOnlyCollection<Exception> ?? e.ToList();
                    continue;
                }

                if (se.Name == "StackTraceString")
                {
                    var stackTrace = se.Value?.ToString();
                    if (stackTrace.NotNullNorEmpty())
                    {
                        writer.WriteLine("Stack Trace:");
                        WriteText(writer, null, stackTrace);
                    }
                    else
                    {
                        writer.WriteLine("Stack Trace: <unavailable>");
                        if (captureStackTrace)
                            WriteText(writer, null, new StackTrace(skipFrames: 2, fNeedFileInfo: true).ToString());
                    }
                }
                else if (se.Name == "RemoteStackTraceString")
                {
                    if (se.Value != null)
                    {
                        writer.WriteLine("Remote Stack Trace:");
                        WriteText(writer, null, se.Value.ToString());
                    }
                }
                else if (se.Value is IDictionary dictionary)
                {
                    writer.WriteLine($"{se.Name}: {{");
                    writer.Indent++;

                    var enumerator = dictionary.GetEnumerator();
                    while (enumerator.MoveNext())
                    {
                        var de = enumerator.Entry;
                        writer.WriteLine("    {0} = {1}", de.Key, de.Value ?? "<null>");
                    }

                    writer.Indent--;
                    writer.WriteLine("}");
                }
                else if (!(se.Value is string) && se.Value is IEnumerable enumerable)
                {
                    writer.WriteLine("{0}:", se.Name);
                    writer.Write("    [");

                    var index = 0;
                    foreach (var value in enumerable)
                    {
                        if (index++ != 0)
                            writer.Write(", ");

                        writer.Write(value?.ToString() ?? "<null>");
                    }

                    writer.WriteLine("]");
                }
                else if (se.Value != null)
                {
                    WriteText(writer, se.Name, se.Value.ToString());
                }
            }

            if (exceptions != null)
            {
                var index = 0;
                foreach (var innerException in exceptions)
                {
                    writer.WriteLine("Inner Exception #{0}:", index++.ToString(CultureInfo.InvariantCulture));
                    writer.Indent++;
                    FormatExceptionImpl(writer, innerException, false);
                    writer.Indent--;
                }
            }

            if (exception.InnerException != null && exceptions?.Contains(exception.InnerException) != true)
            {
                writer.WriteLine("Inner Exception:");
                writer.Indent++;
                FormatExceptionImpl(writer, exception.InnerException, false);
                writer.Indent--;
            }
        }

        private static void WriteText(IndentedTextWriter writer, [CanBeNull] string name, [CanBeNull] string value)
        {
            if (value.IsNullOrEmpty())
                return;

            if (value.IndexOfAny(_separator) != -1)
            {
                if (name.NotNullNorEmpty())
                    writer.WriteLine("{0}:", name);

                writer.Indent++;

                var reader = new StringReader(value);
                while (reader.Peek() != -1)
                {
                    // ReSharper disable once PossibleNullReferenceException
                    var line = reader.ReadLine().TrimStart();
                    if (line.Length != 0)
                        writer.WriteLine(line);
                }

                writer.Indent--;
            }
            else if (name.IsNullOrEmpty())
            {
                writer.WriteLine(value);
            }
            else
            {
                writer.WriteLine("{0}: {1}", name, value);
            }
        }
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re: [FeatureRequest] [Review] FormatterException
От: Sinix  
Дата: 10.03.17 15:08
Оценка:
Здравствуйте, rameel, Вы писали:

R>2IT: Предложения по свежим сбросам[/url]. Решил все-таки его причесать и переписать с использованием SerializationInfo. Стоит заменить текущую реализцию в проекте?




Такой вопрос: а SerializationInfo будет корректно работать для исключений, которые содержат non-serializable данные?
Re[2]: [FeatureRequest] [Review] FormatterException
От: rameel https://github.com/rsdn/CodeJam
Дата: 12.03.17 13:46
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Такой вопрос: а SerializationInfo будет корректно работать для исключений, которые содержат non-serializable данные?


Неа, будет проигнорирован, но таких исключений я встречал только как исключение. Обычно на практике стараются работать по правилам. Вот старый вариант работал через TypeAccessor, но pretty print для исключений понадобился в стороннем проекте, куда не хотели добавлять дополнительных зависимостей. Можно конечно вернуть старый вариант или на худой конец заиспользовать рефлекшн.
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[2]: [FeatureRequest] [Review] FormatterException
От: rameel https://github.com/rsdn/CodeJam
Дата: 12.03.17 13:50
Оценка:
Здравствуйте, Sinix, Вы писали:

S>Такой вопрос: а SerializationInfo будет корректно работать для исключений, которые содержат non-serializable данные?


Прочитал наизнанку У меня цель не стояла сериализация исключений, целью был pretty print, поэтому я только для исключений и использовал механизм с SerializationInfo, а все что туда попадает выводится обычно через ToString(), разве что допольнительно обрабатываю списки и словари
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[3]: [FeatureRequest] [Review] FormatterException
От: Sinix  
Дата: 12.03.17 13:57
Оценка:
Здравствуйте, rameel, Вы писали:

S>>Такой вопрос: а SerializationInfo будет корректно работать для исключений, которые содержат non-serializable данные?

R>Можно конечно вернуть старый вариант или на худой конец заиспользовать рефлекшн.

Ага, тогда в порядке предложения — а какие у нас ещё есть варианты, которые будут работать даже с "неправильными" исключениями?
С учётом временного отсутствия бинарной сериализации в .net core — или рефлексия, или дескриптор, или codegen (недоступный в .net native). Ничего не упустил?
Re[4]: [FeatureRequest] [Review] FormatterException
От: rameel https://github.com/rsdn/CodeJam
Дата: 26.03.17 10:51
Оценка:
Здравствуйте, Sinix, Вы писали:

S>С учётом временного отсутствия бинарной сериализации в .net core — или рефлексия, или дескриптор, или codegen (недоступный в .net native).


Прошу прощения, название Formatter вводит в заблуждение Под фичреквестом я хотел заменить всего-лишь реализацию ToDiagnosticString на тот, что стартовом сообщении
... << RSDN@Home 1.0.0 alpha 5 rev. 0>>
Re[5]: [FeatureRequest] [Review] FormatterException
От: Sinix  
Дата: 26.03.17 19:58
Оценка:
Здравствуйте, rameel, Вы писали:

R>Прошу прощения, название Formatter вводит в заблуждение Под фичреквестом я хотел заменить всего-лишь реализацию ToDiagnosticString на тот, что стартовом сообщении

Да не, я всё правильно понял. Меня смущает, что в новой версии pretty print не будет работать, если автор исключения забыл про сериализацию.

Или я неправ и всё ок?
Сорри, последнее время загружен капитально, даже на выходных самому проверить влом
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.