Chuyển đổi ngoại lệ WHOLE thành chuỗi
Gọi điện Exception.ToString()
cho bạn nhiều thông tin hơn là chỉ sử dụng Exception.Message
tài sản. Tuy nhiên, ngay cả điều này vẫn để lại nhiều thông tin, bao gồm:
- Các
Data
tài sản bộ sưu tập được tìm thấy trên tất cả các ngoại lệ.
- Bất kỳ thuộc tính tùy chỉnh khác được thêm vào ngoại lệ.
Có những lúc bạn muốn nắm bắt thông tin thêm này. Mã dưới đây xử lý các tình huống trên. Nó cũng viết ra các thuộc tính của các ngoại lệ theo một thứ tự tốt đẹp. Đó là sử dụng C # 7 nhưng sẽ rất dễ dàng để bạn chuyển đổi sang các phiên bản cũ hơn nếu cần thiết. Xem thêm câu trả lời liên quan này .
public static class ExceptionExtensions
{
public static string ToDetailedString(this Exception exception) =>
ToDetailedString(exception, ExceptionOptions.Default);
public static string ToDetailedString(this Exception exception, ExceptionOptions options)
{
if (exception == null)
{
throw new ArgumentNullException(nameof(exception));
}
var stringBuilder = new StringBuilder();
AppendValue(stringBuilder, "Type", exception.GetType().FullName, options);
foreach (PropertyInfo property in exception
.GetType()
.GetProperties()
.OrderByDescending(x => string.Equals(x.Name, nameof(exception.Message), StringComparison.Ordinal))
.ThenByDescending(x => string.Equals(x.Name, nameof(exception.Source), StringComparison.Ordinal))
.ThenBy(x => string.Equals(x.Name, nameof(exception.InnerException), StringComparison.Ordinal))
.ThenBy(x => string.Equals(x.Name, nameof(AggregateException.InnerExceptions), StringComparison.Ordinal)))
{
var value = property.GetValue(exception, null);
if (value == null && options.OmitNullProperties)
{
if (options.OmitNullProperties)
{
continue;
}
else
{
value = string.Empty;
}
}
AppendValue(stringBuilder, property.Name, value, options);
}
return stringBuilder.ToString().TrimEnd('\r', '\n');
}
private static void AppendCollection(
StringBuilder stringBuilder,
string propertyName,
IEnumerable collection,
ExceptionOptions options)
{
stringBuilder.AppendLine($"{options.Indent}{propertyName} =");
var innerOptions = new ExceptionOptions(options, options.CurrentIndentLevel + 1);
var i = 0;
foreach (var item in collection)
{
var innerPropertyName = $"[{i}]";
if (item is Exception)
{
var innerException = (Exception)item;
AppendException(
stringBuilder,
innerPropertyName,
innerException,
innerOptions);
}
else
{
AppendValue(
stringBuilder,
innerPropertyName,
item,
innerOptions);
}
++i;
}
}
private static void AppendException(
StringBuilder stringBuilder,
string propertyName,
Exception exception,
ExceptionOptions options)
{
var innerExceptionString = ToDetailedString(
exception,
new ExceptionOptions(options, options.CurrentIndentLevel + 1));
stringBuilder.AppendLine($"{options.Indent}{propertyName} =");
stringBuilder.AppendLine(innerExceptionString);
}
private static string IndentString(string value, ExceptionOptions options)
{
return value.Replace(Environment.NewLine, Environment.NewLine + options.Indent);
}
private static void AppendValue(
StringBuilder stringBuilder,
string propertyName,
object value,
ExceptionOptions options)
{
if (value is DictionaryEntry)
{
DictionaryEntry dictionaryEntry = (DictionaryEntry)value;
stringBuilder.AppendLine($"{options.Indent}{propertyName} = {dictionaryEntry.Key} : {dictionaryEntry.Value}");
}
else if (value is Exception)
{
var innerException = (Exception)value;
AppendException(
stringBuilder,
propertyName,
innerException,
options);
}
else if (value is IEnumerable && !(value is string))
{
var collection = (IEnumerable)value;
if (collection.GetEnumerator().MoveNext())
{
AppendCollection(
stringBuilder,
propertyName,
collection,
options);
}
}
else
{
stringBuilder.AppendLine($"{options.Indent}{propertyName} = {value}");
}
}
}
public struct ExceptionOptions
{
public static readonly ExceptionOptions Default = new ExceptionOptions()
{
CurrentIndentLevel = 0,
IndentSpaces = 4,
OmitNullProperties = true
};
internal ExceptionOptions(ExceptionOptions options, int currentIndent)
{
this.CurrentIndentLevel = currentIndent;
this.IndentSpaces = options.IndentSpaces;
this.OmitNullProperties = options.OmitNullProperties;
}
internal string Indent { get { return new string(' ', this.IndentSpaces * this.CurrentIndentLevel); } }
internal int CurrentIndentLevel { get; set; }
public int IndentSpaces { get; set; }
public bool OmitNullProperties { get; set; }
}
Mẹo hàng đầu - Ghi nhật ký ngoại lệ
Hầu hết mọi người sẽ sử dụng mã này để đăng nhập. Cân nhắc sử dụng Serilog với gói NuGet Serilog.Exceptions của tôi , nó cũng ghi lại tất cả các thuộc tính của một ngoại lệ nhưng nó nhanh hơn và không có sự phản chiếu trong phần lớn các trường hợp. Serilog là một khung đăng nhập rất tiên tiến, đó là tất cả các cơn thịnh nộ tại thời điểm viết.
Mẹo hàng đầu - Dấu vết ngăn xếp có thể đọc được của con người
Bạn có thể sử dụng Ben.Demystifier gói NuGet để có được đống dấu vết có thể đọc được con người cho trường hợp ngoại lệ của bạn hoặc serilog-enrichers-sáng tỏ gói NuGet nếu bạn đang sử dụng Serilog.