为啥我不能使用 ProtoBuf-Net 正确反序列化我的对象?

Posted

技术标签:

【中文标题】为啥我不能使用 ProtoBuf-Net 正确反序列化我的对象?【英文标题】:Why can I not deserialize my object correctly using ProtoBuf-Net?为什么我不能使用 ProtoBuf-Net 正确反序列化我的对象? 【发布时间】:2014-09-01 00:20:40 【问题描述】:

我刚刚开始使用 ProtoBuf-Net 并拥有以下对象:

[DataContract]
public class Statistics

    [DataMember(Order = 1)]
    public DateTime DateTimeAsUtc  get; set; 

    [DataMember(Order = 2)]
    public IEnumerable<StatisticsRow> TopHashTags  get; set; 

    [DataMember(Order = 3)]
    public IEnumerable<StatisticsRow> TopWords  get; set;     


[DataContract]
public class StatisticsRow

    [DataMember(Order = 1)]
    public string Key  get; set; 

    [DataMember(Order = 2)]
    public int Count  get; set; 



// Serialize then DeSerialize
using (var stream = new MemoryStream())

    Serializer.Serialize(stream, stats);

    stream.Seek(0, SeekOrigin.Begin);
    var deserialized = Serializer.Deserialize<Statistics>(stream);

当我序列化并尝试反序列化对象时,我得到了所有其他属性的 DateTimeAsUtcnull 的默认值。关于我做错了什么有什么想法吗?

请注意,我尝试将 DataContractDataMember 替换为 ProtoContractProtoMember 无济于事。

该问题仅在 Release 模式下发生。

[更新] 问题原来是由于存在[MyConsoleApp].vshost.exe 显然是a special version of the executable to aid debugging 我认为会在Rebuild 之后重新生成(显然不是)所以解决方案是手动删除它现在一切正常:-)

无论如何,我都会接受 Marc 的回答,因为他很友好地跟进并很快回复。

【问题讨论】:

问题不在于日期时间,如果我删除日期时间,其他属性仍然为空。 输入数据是什么?所以我可以复制? 嗨 Marc,tnx 跟进此事,我将在今晚(伦敦时间)晚些时候更新 q,因为我将在一天中的大部分时间都在工作。很棒的图书馆顺便说一句。 【参考方案1】:

以您的示例为基础,这对我来说很好:

using (var stream = new MemoryStream()) 
    var stats = new Statistics 
        DateTimeAsUtc = DateTime.UtcNow,
        TopWords = new List<StatisticsRow> 
            new StatisticsRow  Count = 1, Key = "abc" 
        ,
        TopHashTags = new List<StatisticsRow> 
            new StatisticsRow  Count = 2, Key = "def" 
        
    ;
    Serializer.Serialize(stream, stats);

    stream.Seek(0, SeekOrigin.Begin);
    var deserialized = Serializer.Deserialize<Statistics>(stream);
    Console.WriteLine(deserialized.DateTimeAsUtc);
    foreach(var row in deserialized.TopWords)
        Console.WriteLine("0: 1", row.Key, row.Count);
    foreach (var row in deserialized.TopHashTags)
        Console.WriteLine("0: 1", row.Key, row.Count);

所以...它可能需要一个完整的(失败的)示例才能回答。然而,首先要检查的是stream.Length;如果那是0,则没有数据序列化。顺便说一句,为了您的方便:该实现类似于:

var deserialized = Serializer.DeepClone(stats);

【讨论】:

这太奇怪了!该问题仅在发布模式下发生并且仅在我正在处理的特定项目中发生,不同项目上的完全相同的代码,例如单元测试使用 ProtoBuf 的相同 nuget 包就可以正常工作。此外,DeepClone 工作得很好,stream.Length 也大于 0

以上是关于为啥我不能使用 ProtoBuf-Net 正确反序列化我的对象?的主要内容,如果未能解决你的问题,请参考以下文章

C# Protobuf-net:小数字典:零不能正确往返

protobuf-net:不正确的线型反序列化 TimeSpan

为啥我的代码中的 protobuf-net 反序列化器比流式读取 csv 慢得多

使用 ProtoBuf-net 反序列化派生类型(字典)未正确设置对象字段

protobuf-net 子消息未正确读取

protobuf-net 生成的 .proto 文件中的字段命名约定不正确?