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为空,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细节。 / p>
有解决方法吗?
答案 0 :(得分:1)
基本上,不,没有解决方法,并且它不是protobuf-net支持的方案。底层协议缓冲区格式(protobuf-net实现)没有null的概念;我无法在常规格式中表示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()
;零长度完全有效,并且在协议缓冲区中定义良好。
与其他一些格式不同,我无法在任何地方添加额外的元数据来表示&#34;我是一个空的&#34; (例如,xml中的@xsi:nil
)。
代码,但我已经检查过,目前还没有对空值的支持 - 我接受这是一个疏忽,但我还要强调,#&#34;保留引用&#34;代码不是标准的protobuf ,任何其他库(java,golang等)都可能难以使用该配置;如果你知道你只是将protobuf-net与protobuf-net谈论,那么我只会提倡。当然,null支持目前还不存在,并且需要黑客攻击:)