protobuf-net :包含空元素的列表


public MyType {
[ProtoMember(1)]
public int Index;
[ProtoMember(2)]
public string Name;
public MyType() {
}
public MyType(int index, string name) {
Index = index;
Name = name;
}
}
var element0 = new MyType(0,"element index 0");
var element1 = null;
var element2 = new MyType(2,"element index 2");
var list = new List<MyType> {element0, element1, element2}

由于元素索引 1 为 null,protobuf-net序列化程序将从序列化字节中省略该元素。

在电线的另一边,发生了一些非常有趣的事情:

protobuf-net反序列化程序读取字节,了解需要 3 个元素,但仅查找元素索引 0 和 2 的字节。 因此,它将元素索引 1 创建为MyType的空实例。

所以反序列化列表等效于:

var element0 = new MyType(0,"element index 0");   
var element1 = new MyType(0,null); 
var element2 = new MyType(2,"element index 2");
var list = new List<MyType> {element0, element1, element2}

但这不是预期的。Null 与空对象不是一回事,并且存在具有重复 Index=0 和 Name=null 的元素可能会对处理代码产生严重的不利后果 - 处理代码理所当然地不应该意识到也不关心 serdes 细节。

有解决方法吗?

基本上,不,没有解决方法,并且在protobuf-net中不支持这种情况。底层协议缓冲区格式(protobuf-net 实现)没有 null 的概念;我无法在常规格式中表示空实例。类列表只是长度前缀节点的重复块,因此(以密集的二进制格式,而不是文本):

[field 1, length-prefixed] [length prefix] [payload for element index 0]
[field 1, length-prefixed] [length prefix] [payload for element index 1]
[field 1, length-prefixed] [length prefix] [payload for element index 2]
... etc

对于列表中的空值,我只有两个选项是:

  • 忽略它们
  • 将它们视为零长度

Protobuf-net目前使用第二种方法,但是:零长度类本质上是new MyType();零长度在协议缓冲区中是完全有效和明确定义的。

与其他一些格式不同,我实际上没有任何地方可以添加额外的元数据来表示"我是空"(例如,在 xml 中@xsi:nil)。

可能会将其破解到"保留引用"代码中,但我已经检查过,目前没有对 null 的支持 - 我接受这有点疏忽,但我还要强调"保留引用"代码不是标准的 protobuf,任何其他库(java、golang 等)可能难以使用该配置;我只会主张,如果你知道你只是在谈论protobuf-net和protobuf-net。当然,空支持目前不存在,需要黑客攻击:)

相关内容

  • 没有找到相关文章

最新更新