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