-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added RolandK.AvaloniaExtensions.ExceptionHandling
- Loading branch information
1 parent
423ee42
commit e316999
Showing
20 changed files
with
672 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
...RolandK.AvaloniaExtensions.ExceptionHandling/Data/Analyzers/AggregateExceptionAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data.Analyzers; | ||
|
||
public class AggregateExceptionAnalyzer : IExceptionAnalyzer | ||
{ | ||
/// <inheritdoc /> | ||
public IEnumerable<ExceptionProperty>? ReadExceptionInfo(Exception ex) | ||
{ | ||
return null; | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<Exception>? GetInnerExceptions(Exception ex) | ||
{ | ||
if (ex is AggregateException aggEx) | ||
{ | ||
foreach (var actInnerException in aggEx.InnerExceptions) | ||
{ | ||
yield return actInnerException; | ||
} | ||
} | ||
} | ||
} |
21 changes: 21 additions & 0 deletions
21
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/Analyzers/ArgumentExceptionAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data.Analyzers; | ||
|
||
public class ArgumentExceptionAnalyzer : IExceptionAnalyzer | ||
{ | ||
/// <inheritdoc /> | ||
public IEnumerable<ExceptionProperty>? ReadExceptionInfo(Exception ex) | ||
{ | ||
if (ex is not ArgumentException argumentException) { yield break; } | ||
|
||
yield return new ExceptionProperty("ParamName", argumentException.ParamName ?? string.Empty); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<Exception>? GetInnerExceptions(Exception ex) | ||
{ | ||
return null; | ||
} | ||
} |
39 changes: 39 additions & 0 deletions
39
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/Analyzers/DefaultExceptionAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data.Analyzers; | ||
|
||
public class DefaultExceptionAnalyzer : IExceptionAnalyzer | ||
{ | ||
/// <inheritdoc /> | ||
public IEnumerable<ExceptionProperty>? ReadExceptionInfo(Exception ex) | ||
{ | ||
yield return new ExceptionProperty("Type", ex.GetType().FullName ?? string.Empty); | ||
yield return new ExceptionProperty("Message", ex.Message); | ||
yield return new ExceptionProperty("HResult", ex.HResult.ToString()); | ||
yield return new ExceptionProperty("HelpLink", ex.HelpLink ?? string.Empty); | ||
yield return new ExceptionProperty("Source", ex.Source ?? string.Empty); | ||
|
||
if (ex.TargetSite != null) | ||
{ | ||
var sourceMethod = ex.TargetSite; | ||
yield return new ExceptionProperty("SourceMethod.Name", sourceMethod.Name); | ||
yield return new ExceptionProperty("SourceMethod.IsStatic", sourceMethod.IsStatic.ToString()); | ||
yield return new ExceptionProperty( | ||
"SourceMethod.Type", | ||
sourceMethod.DeclaringType?.FullName ?? string.Empty); | ||
} | ||
|
||
yield return new ExceptionProperty("StackTrace", ex.StackTrace ?? string.Empty); | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<Exception>? GetInnerExceptions(Exception ex) | ||
{ | ||
if(ex.InnerException != null) | ||
{ | ||
yield return ex.InnerException; | ||
} | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/Analyzers/SystemIOExceptionAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Text; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data.Analyzers; | ||
|
||
public class SystemIOExceptionAnalyzer : IExceptionAnalyzer | ||
{ | ||
/// <inheritdoc /> | ||
public IEnumerable<ExceptionProperty>? ReadExceptionInfo(Exception ex) | ||
{ | ||
switch (ex) | ||
{ | ||
case FileLoadException fileLoadEx: | ||
yield return new ExceptionProperty("FileName", fileLoadEx.FileName ?? string.Empty); | ||
yield return new ExceptionProperty("FusionLog", fileLoadEx.FusionLog ?? string.Empty); | ||
break; | ||
|
||
case FileNotFoundException fileNotFoundEx: | ||
yield return new ExceptionProperty("FileName", fileNotFoundEx.FileName ?? string.Empty); | ||
yield return new ExceptionProperty("FusionLog", fileNotFoundEx.FusionLog ?? string.Empty); | ||
break; | ||
|
||
case DirectoryNotFoundException: | ||
break; | ||
} | ||
} | ||
|
||
/// <inheritdoc /> | ||
public IEnumerable<Exception>? GetInnerExceptions(Exception ex) | ||
{ | ||
return null; | ||
} | ||
} |
112 changes: 112 additions & 0 deletions
112
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/ExceptionInfo.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
using RolandK.AvaloniaExtensions.ExceptionHandling.Data.Analyzers; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data; | ||
|
||
public class ExceptionInfo | ||
{ | ||
/// <summary> | ||
/// Gets a collection containing all child nodes. | ||
/// </summary> | ||
public List<ExceptionInfoNode> ChildNodes { get; set; } = new(); | ||
|
||
/// <summary> | ||
/// Gets or sets the main message. | ||
/// </summary> | ||
public string MainMessage | ||
{ | ||
get; | ||
set; | ||
} = string.Empty; | ||
|
||
public string Description | ||
{ | ||
get; | ||
set; | ||
} = string.Empty; | ||
|
||
public ExceptionInfo() | ||
{ | ||
|
||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ExceptionInfo"/> class. | ||
/// </summary> | ||
public ExceptionInfo(Exception ex, IEnumerable<IExceptionAnalyzer>? exceptionAnalyzers = null) | ||
{ | ||
exceptionAnalyzers ??= CreateDefaultAnalyzers(); | ||
|
||
this.MainMessage = "Unexpected Error"; | ||
this.Description = ex.Message; | ||
|
||
// Analyze the given exception | ||
ExceptionInfoNode newNode = new(ex); | ||
this.ChildNodes.Add(newNode); | ||
|
||
AnalyzeException(ex, newNode, exceptionAnalyzers); | ||
} | ||
|
||
public static IEnumerable<IExceptionAnalyzer> CreateDefaultAnalyzers() | ||
{ | ||
yield return new DefaultExceptionAnalyzer(); | ||
yield return new SystemIOExceptionAnalyzer(); | ||
yield return new AggregateExceptionAnalyzer(); | ||
yield return new ArgumentExceptionAnalyzer(); | ||
} | ||
|
||
/// <summary> | ||
/// Analyzes the given exception. | ||
/// </summary> | ||
/// <param name="ex">The exception to be analyzed.</param> | ||
/// <param name="targetNode">The target node where to put all data to.</param> | ||
/// <param name="exceptionAnalyzers">All loaded analyzer objects.</param> | ||
private static void AnalyzeException(Exception ex, ExceptionInfoNode targetNode, IEnumerable<IExceptionAnalyzer> exceptionAnalyzers) | ||
{ | ||
// Query over all exception data | ||
var analyzedInnerExceptions = new HashSet<Exception>(2); | ||
foreach(IExceptionAnalyzer actAnalyzer in exceptionAnalyzers) | ||
{ | ||
// Read all properties of the current exception | ||
var exceptionInfos = actAnalyzer.ReadExceptionInfo(ex); | ||
if (exceptionInfos != null) | ||
{ | ||
foreach (ExceptionProperty actProperty in exceptionInfos) | ||
{ | ||
if (string.IsNullOrEmpty(actProperty.Name)) { continue; } | ||
|
||
ExceptionInfoNode propertyNode = new(actProperty); | ||
|
||
targetNode.ChildNodes ??= new List<ExceptionInfoNode>(); | ||
targetNode.ChildNodes.Add(propertyNode); | ||
} | ||
} | ||
|
||
// Read all inner exception information | ||
var innerExceptions = actAnalyzer.GetInnerExceptions(ex); | ||
if (innerExceptions == null) { continue; } | ||
|
||
foreach (Exception actInnerException in innerExceptions) | ||
{ | ||
if(analyzedInnerExceptions.Contains(actInnerException)){ continue; } | ||
analyzedInnerExceptions.Add(actInnerException); | ||
|
||
ExceptionInfoNode actInfoNode = new(actInnerException); | ||
AnalyzeException(actInnerException, actInfoNode, exceptionAnalyzers); | ||
|
||
targetNode.ChildNodes ??= new List<ExceptionInfoNode>(); | ||
targetNode.ChildNodes.Add(actInfoNode); | ||
} | ||
} | ||
|
||
// Sort all generated nodes | ||
if (targetNode.ChildNodes?.Count > 0) | ||
{ | ||
targetNode.ChildNodes.Sort(); | ||
} | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/ExceptionInfoNode.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
using System; | ||
using System.Reflection; | ||
using System.Collections.Generic; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data; | ||
|
||
public class ExceptionInfoNode : IComparable<ExceptionInfoNode> | ||
{ | ||
/// <summary> | ||
/// Gets a collection containing all child nodes. | ||
/// </summary> | ||
public List<ExceptionInfoNode>? ChildNodes { get; set; } | ||
|
||
public bool IsExceptionNode { get; set; } | ||
|
||
public string PropertyName { get; set; } = string.Empty; | ||
|
||
public string PropertyValue { get; set; } = string.Empty; | ||
|
||
public ExceptionInfoNode() | ||
{ | ||
|
||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="ExceptionInfoNode"/> class. | ||
/// </summary> | ||
public ExceptionInfoNode(Exception ex) | ||
{ | ||
this.IsExceptionNode = true; | ||
this.PropertyName = ex.GetType().GetTypeInfo().Name; | ||
this.PropertyValue = ex.Message; | ||
} | ||
|
||
public ExceptionInfoNode(ExceptionProperty property) | ||
{ | ||
this.PropertyName = property.Name; | ||
this.PropertyValue = property.Value; | ||
} | ||
|
||
public int CompareTo(ExceptionInfoNode? other) | ||
{ | ||
if (other == null) { return -1; } | ||
if(this.IsExceptionNode != other.IsExceptionNode) | ||
{ | ||
if (this.IsExceptionNode) { return 1; } | ||
else { return -1; } | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return $"{this.PropertyName}: {this.PropertyValue}"; | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/ExceptionProperty.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data; | ||
|
||
public class ExceptionProperty(string name, string value) | ||
{ | ||
public string Name { get; } = name; | ||
public string Value { get; } = value; | ||
|
||
public override string ToString() | ||
{ | ||
return $"{this.Name}: {this.Value}"; | ||
} | ||
} |
27 changes: 27 additions & 0 deletions
27
src/RolandK.AvaloniaExtensions.ExceptionHandling/Data/IExceptionAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
namespace RolandK.AvaloniaExtensions.ExceptionHandling.Data; | ||
|
||
/// <summary> | ||
/// This interface is used by the error-reporting framework. | ||
/// It queries for all information provided by an exception which will be presented to | ||
/// the user / developer. | ||
/// </summary> | ||
public interface IExceptionAnalyzer | ||
{ | ||
/// <summary> | ||
/// Reads all exception information from the given exception object. | ||
/// </summary> | ||
/// <param name="ex">The exception to be analyzed.</param> | ||
IEnumerable<ExceptionProperty>? ReadExceptionInfo(Exception ex); | ||
|
||
/// <summary> | ||
/// Gets all inner exceptions provided by the given exception object. | ||
/// </summary> | ||
/// <param name="ex">The exception to be analyzed.</param> | ||
IEnumerable<Exception>? GetInnerExceptions(Exception ex); | ||
} |
Oops, something went wrong.