使用Protobuf .net反序列化单个结构字段

时间:2012-09-24 13:09:54

标签: c# protobuf-net

我有一个关于使用Protobuf .Net进行反序列化的问题。我试图用它替换XMLSerializer,我找不到从文件反序列化单个字段的方法 如果文件被修改,我需要信息,这是保存结构中的一个字段。

甚至可能吗?如果是的话,我可以寻求帮助吗?

此致

1 个答案:

答案 0 :(得分:4)

在大多数情况下,坦率地说,你可以直接反序列化整个事情 - 它会很快等等。但是,如果真的想要限制它,那么有几个选项。

最简单的方法就是创建一个更小的模型,只需要你想要的信息。所以:如果您的原始模型上有46个字段,其中5个是集合等 - 但您只需要字段12中的Version,然后:

[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”。通过指示,它是“最后的价值获胜”,因此上述中的短路(理论上)可以给出不同的答案。然而!这是非常不可能的,如果您正在利用附加消息,通常知道。这根本不适用于大多数人。