Protobuf-Net清​​单

时间:2013-05-05 21:17:54

标签: c# protobuf-net

遇到了protobuf-net,太棒了!我有一个关于空列表序列化的问题。

我首先声明要序列化的对象:

[ProtoContract]
class TestClass
{
    [ProtoMember(1)]
    List<int> _listOfInts = new List<int>();

    public TestClass() { }

    public List<int> ListOfInts
    {
        get { return _listOfInts; }
        set { _listOfInts = value; }
    }
}

如果_listOfInts为空(但不为null),当我deserialse时,此对象将始终为null。这对于protobuf约定是有意义的,我目前通过添加以下方法来解决这个问题:

[ProtoAfterDeserialization]
private void OnDeserialize()
{
    if (_listOfInts == null)
        _listOfInts = new List<int>();
}

我的问题是我是否能够以更简洁的方式实现相同的功能,可能还有一个额外的attirbute,它会将null / empty对象初始化为空而不是null?

2 个答案:

答案 0 :(得分:6)

这里有一个关于protobuf如何编码数据的基本问题:列表本身在数据中不会出现 - 只是元素。因此,存储有关列表的信息是显而易见的。它可以通过使用条件序列化发送布尔值来欺骗,但坦率地说这有点hacky和丑陋 - 并增加了复杂性。就个人而言,我强烈建议从可能为空的列表中抽象出来。例如:

private readonly List<Foo> items = new List<Foo>();
[ProtoMember(1)]
public List<Foo> Items { get { return items; } }

或者

private List<Foo> items;
[ProtoMember(1)]
public List<Foo> Items { get { return items ?? (items = new List<Foo>()); } }

请注意,这个建议不只是关于序列化:它是关于避免任意的空引用异常。人们通常不希望子集合为空。

答案 1 :(得分:5)

如果您尝试防止空列表,可以尝试在属性getter中进行延迟加载。

public List<int> ListOfInts
{
    get { return _listOfInts ?? (_listOfInts = new List<int>()); }
    set { _listOfInts = value; }
}

这样您就可以让序列化程序返回null。