我有一个关于使用 Protobuf .Net 进行反序列化的问题。我正在尝试用它替换 XMLSerializer,但我找不到从文件中反序列化单个字段的方法。
如果文件被修改,我需要信息,这是保存结构中的字段之一。
甚至可能吗?如果是,我可以寻求帮助吗?
问候
我有一个关于使用 Protobuf .Net 进行反序列化的问题。我正在尝试用它替换 XMLSerializer,但我找不到从文件中反序列化单个字段的方法。
如果文件被修改,我需要信息,这是保存结构中的字段之一。
甚至可能吗?如果是,我可以寻求帮助吗?
问候
在大多数情况下,坦率地说,你可以反序列化整个事情——它会很快,等等。但是,如果你真的想限制它,有几个选项。
最简单的方法是创建一个较小的模型,上面只包含您想要的信息。所以:如果您的原始模型上有 46 个字段,其中 5 个是集合等 - 但您只想要Version
字段 12 中的字段,那么:
[ProtoContract]
public class InsertNameHere {
[ProtoMember(12)]
public int Version {get;set;}
}
现在反序列化:
var obj = Serializer.Deserialize<InsertNameHere>(source);
int version = obj.Version;
这将起作用,因为 protobuf-net 是基于合同的;它不必是完全相同的类型,只要它看起来足够接近即可。但是,更高级的方法是使用ProtoReader
:
int version = 0;
using (var reader = new ProtoReader(source, RuntimeTypeModel.Default, null))
{
int field;
bool keepReading = true;
while ((field = reader.ReadFieldHeader()) > 0 && keepReading)
{
switch (field)
{
case 12:
version = reader.ReadInt32();
// STOP LOOPING (leaves the stream partly-read)
keepReading = false;
break;
default:
reader.SkipField();
break;
}
}
}
您可能想要使用上述内容的原因是它可以更早地停止查找- 即,一旦我们找到我们的字段 12,我们就可以在不处理文件的其余部分的情况下杀死阅读器。通常,如果我们知道数据很大并且我们不想要太多数据,我只会使用第二种方法。
从技术上讲, protobuf 是一种可附加格式,有一个小问题,所以理论上文件末尾可能还有另一个“字段 12”。按照规范,它是“最后的价值获胜”,所以上面的短路可以(理论上)给你一个不同的答案。然而!这是非常不可能的,您通常会知道您是否正在利用附加消息。这根本不适用于大多数人。