-
Notifications
You must be signed in to change notification settings - Fork 24
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Try to keep useful information from the non-serializable exceptions.
- Loading branch information
Showing
7 changed files
with
230 additions
and
15 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 was deleted.
Oops, something went wrong.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System; | ||
using System.Linq; | ||
|
||
namespace CoreRemoting.Serialization; | ||
|
||
/// <summary> | ||
/// Extension methods for the exception classes. | ||
/// </summary> | ||
public static class ExceptionExtensions | ||
{ | ||
/// <summary> | ||
/// Checks whether the exception is serializable. | ||
/// </summary> | ||
public static bool IsSerializable(this Exception ex) => ex switch | ||
{ | ||
null => true, | ||
|
||
AggregateException agg => | ||
agg.InnerExceptions.All(ix => ix.IsSerializable()) && | ||
agg.InnerException.IsSerializable() && | ||
agg.GetType().IsSerializable, | ||
|
||
_ => ex.GetType().IsSerializable && | ||
ex.InnerException.IsSerializable() | ||
}; | ||
|
||
/// <summary> | ||
/// Converts the non-serializable exception to a serializable copy. | ||
/// </summary> | ||
public static Exception ToSerializable(this Exception ex) => | ||
ex.IsSerializable() ? ex : | ||
new SerializableException(ex.GetType().Name, ex.Message, | ||
ex.InnerException.ToSerializable(), ex.StackTrace) | ||
.CopyDataFrom(ex); | ||
|
||
/// <summary> | ||
/// Copies all exception data slots from the original exception. | ||
/// </summary> | ||
/// <typeparam name="TException">Exception type.</typeparam> | ||
/// <param name="ex">Target exception.</param> | ||
/// <param name="original">Original exception.</param> | ||
/// <returns>Modified target exception.</returns> | ||
public static TException CopyDataFrom<TException>(this TException ex, Exception original) | ||
where TException : Exception | ||
{ | ||
if (ex == null || original == null) | ||
return ex; | ||
|
||
foreach (var key in original.Data.Keys) | ||
ex.Data[key] = original.Data[key]; | ||
|
||
return ex; | ||
} | ||
|
||
/// <summary> | ||
/// Returns the most inner exception. | ||
/// </summary> | ||
public static Exception GetInnermostException(this Exception ex) | ||
{ | ||
while (ex?.InnerException != null) | ||
ex = ex.InnerException; | ||
|
||
return ex; | ||
} | ||
} |
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,103 @@ | ||
using System; | ||
using System.Runtime.Serialization; | ||
|
||
namespace CoreRemoting.Serialization; | ||
|
||
/// <summary> | ||
/// Serializable exception replacement for non-serializable exceptions. | ||
/// </summary> | ||
[Serializable] | ||
public class SerializableException : Exception | ||
{ | ||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SerializableException"/> class. | ||
/// </summary> | ||
/// <param name="typeName">Source exception type name.</param> | ||
/// <param name="message">The message.</param> | ||
public SerializableException(string typeName, string message) | ||
: base(message) | ||
{ | ||
SourceTypeName = typeName; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SerializableException"/> class. | ||
/// </summary> | ||
/// <param name="typeName">Source exception type name.</param> | ||
/// <param name="message">The message.</param> | ||
/// <param name="innerException">The inner exception.</param> | ||
public SerializableException(string typeName, string message, Exception innerException) | ||
: base(message, innerException) | ||
{ | ||
SourceTypeName = typeName; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SerializableException"/> class. | ||
/// </summary> | ||
/// <param name="typeName">Source exception type name.</param> | ||
/// <param name="message">The message.</param> | ||
/// <param name="newStackTrace">The new stack trace.</param> | ||
public SerializableException(string typeName, string message, string newStackTrace) | ||
: base(message) | ||
{ | ||
SourceTypeName = typeName; | ||
stackTrace = newStackTrace; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SerializableException"/> class. | ||
/// </summary> | ||
/// <param name="typeName">Source exception type name.</param> | ||
/// <param name="message">The message.</param> | ||
/// <param name="innerException">The inner exception.</param> | ||
/// <param name="newStackTrace">The new stack trace.</param> | ||
public SerializableException(string typeName, string message, Exception innerException, string newStackTrace) | ||
: base(message, innerException) | ||
{ | ||
SourceTypeName = typeName; | ||
stackTrace = newStackTrace; | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="SerializableException"/> class. | ||
/// </summary> | ||
/// <param name="info">The object that holds the serialized object data.</param> | ||
/// <param name="context">The contextual information about the source or destination.</param> | ||
protected SerializableException(SerializationInfo info, StreamingContext context) | ||
: base(info, context) | ||
{ | ||
stackTrace = info.GetString("MyStackTrace"); | ||
SourceTypeName = info.GetString("SourceTypeName"); | ||
} | ||
|
||
/// <summary> | ||
/// Sets the <see cref="T:System.Runtime.Serialization.SerializationInfo" /> with information about the exception. | ||
/// </summary> | ||
/// <param name="info">The <see cref="T:System.Runtime.Serialization.SerializationInfo" /> that holds | ||
/// the serialized object data about the exception being thrown.</param> | ||
/// <param name="context">The <see cref="T:System.Runtime.Serialization.StreamingContext" /> that contains | ||
/// contextual information about the source or destination.</param> | ||
public override void GetObjectData(SerializationInfo info, StreamingContext context) | ||
{ | ||
base.GetObjectData(info, context); | ||
info.AddValue("MyStackTrace", stackTrace); | ||
info.AddValue("SourceTypeName", SourceTypeName); | ||
} | ||
|
||
private string stackTrace; | ||
|
||
/// <summary> | ||
/// Gets a string representation of the immediate frames on the call stack. | ||
/// </summary> | ||
/// <returns>A string that describes the immediate frames of the call stack.</returns> | ||
/// <PermissionSet> | ||
/// <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" PathDiscovery="*AllFiles*"/> | ||
/// </PermissionSet> | ||
public override string StackTrace => stackTrace ?? base.StackTrace; | ||
|
||
/// <summary> | ||
/// Gets the type name of source exception. | ||
/// </summary> | ||
public string SourceTypeName { get; private set; } | ||
} |