स्ट्रिंग अपवाद को एक स्ट्रिंग में परिवर्तित करना
कॉलिंग Exception.ToString()
आपको Exception.Message
संपत्ति का उपयोग करने की तुलना में अधिक जानकारी देता है। हालाँकि, यह अभी भी बहुत सारी जानकारी को छोड़ देता है, जिसमें शामिल हैं:
Data
संग्रह संपत्ति सभी अपवादों पर पाया।
- किसी भी अन्य कस्टम गुण अपवाद में जोड़े गए।
ऐसे समय होते हैं जब आप इस अतिरिक्त जानकारी को कैप्चर करना चाहते हैं। नीचे दिए गए कोड उपरोक्त परिदृश्यों को संभालते हैं। यह एक अच्छा क्रम में अपवादों के गुणों को भी लिखता है। यह C # 7 का उपयोग कर रहा है, लेकिन यदि आवश्यक हो तो पुराने संस्करणों में बदलना आपके लिए बहुत आसान होना चाहिए। इससे संबंधित उत्तर भी देखें ।
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; }
}
शीर्ष टिप - लॉगिंग अपवाद
अधिकांश लोग लॉगिंग के लिए इस कोड का उपयोग करेंगे। मेरे Serilog.Exception NuGet पैकेज के साथ Serilog का उपयोग करने पर विचार करें , जो अपवाद के सभी गुणों को भी लॉग करता है, लेकिन अधिकांश मामलों में यह तेजी से और प्रतिबिंब के बिना करता है। सेरिलॉग एक बहुत ही उन्नत लॉगिंग फ्रेमवर्क है जो लेखन के समय सभी गुस्से में है।
शीर्ष टिप - मानव पठनीय स्टैक निशान
यदि आप Serilog का उपयोग कर रहे हैं तो आप अपने अपवादों या Serilog-richers-demystify NuGet पैकेज के लिए मानव पठनीय स्टैक निशान पाने के लिए Ben.Demystifier NuGet पैकेज का उपयोग कर सकते हैं ।