MessagePack-CSharp / MessagePack-CSharp/MessagePack-CSharp
Null value received in a custom formatter for Exception
還沒有人認領這個 Issue。
- 主要語言
- C#
- 星號
- 6.8k
- 分支
- 775
- 平均合併
- 3 小時 26 分鐘
- 30 天內合併 PR
- 6
描述
Bug description
When trying to serialize/deserialize an exception object using TypelessContractlessStandardResolver, some details like StackTrace and Source are getting lost on the deserialized object.
Hence, I tried to write a custom IMessagePackFormatter. There are two scenarios now :
-
Serialize an exception with no inner exception
The value parameter received in Serialize method is always null
-
Serialize an exception with inner exception
The value parameter received in Serialize method is the inner exception and not the actual exception that was passed for serialization
As a result, I am not able to get a workaround even with a custom IMessagePackFormatter.
Repro steps
- Add a custom IMessagePackFormatter
internal class ExceptionFormatter : IMessagePackFormatter<Exception>
{
public Exception Deserialize(ref MessagePackReader reader, MessagePackSerializerOptions options)
{
}
public void Serialize(ref MessagePackWriter writer, Exception value, MessagePackSerializerOptions options)
{
/// value is null here if exception has no inner exception else inner exception instead of actual exception passed for serialization
}
}
- Configure a custom resolver to use the custom ExceptionFormatter
interface ISerializer
{
byte[] Serialize(object obj);
T Deserialize<T>(byte[] bytes);
}
public class MessagePackTypeLessSerializer : ISerializer
{
private static MessagePackSerializerOptions serializerOptions;
static MessagePackTypeLessSerializer()
{
var resolver = CompositeResolver.Create(
[new ExceptionFormatter()],
[TypelessContractlessStandardResolver.Instance]);
serializerOptions = MessagePackSerializerOptions.Standard.WithResolver(resolver); ;
}
public byte[] Serialize(object obj)
{
return MessagePackSerializer.Typeless.Serialize(obj, serializerOptions);
}
public T Deserialize<T>(byte[] bytes)
{
if (MessagePackSerializer.Typeless.Deserialize(bytes, serializerOptions) is T result)
{
return result;
}
throw new ArgumentException($"Deserialized object is not of type {typeof(T)}");
}
}
- Throw an exception and try to serialize
ISerializer serializer = new MessagePackContractLessSerializer();
var exception = GetException();
var exceptionSerialized = serializer.Serialize(exception);
Exception GetException()
{
try
{
throw new InvalidOperationException("Invalid Operation");
//throw new InvalidOperationException("Invalid Operation", new ArgumentException("Inner Exception"));
}
catch (Exception ex)
{
return ex;
}
}
Expected behavior
Correct exception object should be received in Serialize method of the IMessagePackFormatter that was passed for serialization.
Actual behavior
null/inner exception object is received in Serialize method of the IMessagePackFormatter instead of actual exception passed for serialization.
Version used:
.Net Core 8.0 , MessagePack 2.5.172 : Broken
.Net Framework 4.7, MessagePack 2.5.172 : Partly broken (When no inner exception, we get the correct value. Same as .net core when there is inner exception)
貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
研究方向
首先,使用 issue 中展示的 TypelessContractlessStandardResolver 和 MessagePackSerializerOptions 重現自訂 IMessagePackFormatter 情境,並比較 .NET Core 8.0 與 .NET Framework 4.7 的行為。追蹤 typeless 序列化和 resolver 路徑,以判斷為什麼 Serialize 會收到 null 或內部例外;當 formatter 在兩種情況下都收到原始 Exception 物件時,即表示完成。
由索引模型根據 Issue 內容生成。
評估
- 技術堆疊
- csharp
- 領域
- backend
- Issue 類型
- 缺陷
- 難度
- 4/5
- 預估耗時
- 3-5 天
- 活躍度
- 停滯
- 描述清晰度
- 基本清楚
- 新手友好度
- 38/100