Protobuf-Net 总是反序列化一个空列表

Posted

技术标签:

【中文标题】Protobuf-Net 总是反序列化一个空列表【英文标题】:Protobuf-Net always deserializes an empty list 【发布时间】:2014-07-21 11:21:54 【问题描述】:

以下代码显示了我如何尝试使用 Protobuf-Net 序列化/反序列化列表。方法getNewItem()返回一个ItemsStore的对象,添加到List中。

// Create an empty list
private ItemsStoreList text;

// Add some elements to the list
lock (text.SyncRoot)

    text.AddItem(getNewItem());
    text.AddItem(getNewItem());
    text.AddItem(getNewItem());


// Serialize
var file = File.Create("testfile.bin");
Serializer.Serialize<ItemsStoreList>(file, text);

// Deserialize
ItemsStoreList textNew = Serializer.Deserialize<ItemsStoreList>(file);

运行此代码后,对象textNew 中包含的列表始终为空。对象textNew从类ItemsStoreList实例化,如下所示:

[ProtoContract]
public class ItemsStoreList

    [ProtoMember(1)]
    private List<ItemsStore> m_listData;

    private readonly object m_SyncRoot = new object();

    public ItemsStoreList()
    
        m_listData = new List<ItemsStore>();
    

    public void AddItem(ItemsStore item)
    
        m_listData.Add(item);
    

    public object SyncRoot
    
        get  return this.m_SyncRoot; 
    

    public int Count
    
        get  return m_listData.Count; 
    

    public ItemsStore getItem(int idx)
    
        return (ItemsStore)m_listData[idx];
    

    public void Clear()
    
        m_listData.Clear();
    


[ProtoContract]
public class ItemsStore

    [ProtoMember(1)]
    public myStruct m_Text;
    [ProtoMember(2)]
    public ulong m_Time;

    public ItemsStore(myStruct newText, ulong newTime)
    
        m_Text = newText;
        m_Time = newTime;
    

    public myStruct Text
    
        get  return m_Text; 
    

    public ulong Time
    
        get  return m_Time; 
    


[ProtoContract]
public struct myStruct

    [ProtoMember(1)]
    public uint var1;

    [ProtoMember(2)]
    public byte var2;

    [ProtoMember(3)]
    public byte[] var3;

    [ProtoMember(4)]
    public string var4;

【问题讨论】:

只是额外的,但请注意,“可变结构”实际上比您想象的更容易解决,这要归功于 protobuf-net 的自动元组处理:如果类型没有 proto 属性,但有具有与公共成员完全匹配的参数的构造函数,它假定构造函数演示了意图;例如:pastie.org/9409395 【参考方案1】:

我注意到的第一件事是你没有倒带;添加这个(在序列化和反序列化之间)会改变行为:

file.Position = 0;

我们现在得到一个与 ItemsStore 构造函数相关的异常,因此我们可以指示 protobuf-net 完全忽略该构造函数:

[ProtoContract(SkipConstructor = true)]
public class ItemsStore

现在我们得到了 3 件物品:

System.Console.WriteLine(textNew.Count);

哪个输出:

3

进一步探测表明它很可能也在获取其他数据:

for (int i = 0; i < textNew.Count; i++)

    var item = textNew.getItem(i);
    System.Console.WriteLine(item.m_Text.var1);
    System.Console.WriteLine(item.m_Time);

不过,我将添加关于可变结构和公共字段的强制性警告。

【讨论】:

以上是关于Protobuf-Net 总是反序列化一个空列表的主要内容,如果未能解决你的问题,请参考以下文章

protobuf-net 可以用来(反)序列化包含异构对象的列表吗?

protobuf-net v3 中的数组或列表中的空对象

我可以使用 protobuf-net 在 Mono 中序列化一个对象(包含成员:​​字典、列表...等)并在 MS.NET 中反序列化它,反之亦然?

如何使用 protobuf-net 序列化/反序列化锯齿状/嵌套数组?

Protobuf-net / NetCore2:反序列化忽略带注释的私有字段

带有枚举的 Protobuf-net 反序列化异常