我可以使用protobuf-net作为类似SAX的解析器而没有完整的类型定义吗?

时间:2013-02-26 17:57:56

标签: protobuf-net

有人提到here protobuf-net可以像SAX解析器一样使用,但是我找不到这样的示例,它不需要或多或少地完整描述要解析的对象。

(跳到 2)这个问题, 1)只提供一些背景信息)

1)也许我应首先提供一些背景信息:

我目前在我的项目中使用JSON.Net,并创建了几个JSONConverters自定义类型如何不同的序列化 - 基本上所有主要类型有手写的序列化指令(读属性,ReadValue,等等。)

我做这个的原因和地点的一些例子:

  • 我有一个MetaType类,它描述了某些Value对象在运行时的行为。这些Value对象具有序列化的Type属性。在序列化此属性时,Converter仅返回MetaType的名称,并在反序列化时使用该名称获取对应的MetaType。这样做的原因是类型的名称已经足够,MetaType类过于繁琐而无法序列化,并且生成的JSON更加紧凑。
  • 多个对象的集合包含不需要序列化的值,因为当它们不存在时,我可以基于MetaType重新创建它们。转换器过滤这些集合并仅存储那些非默认值的值 - 而JSON.Net具有阻止属性设置为默认值时被序列化的属性,我不知道有任何内置的方法来过滤默认值来自一个系列。

我的目标是什么:

由于我已经有了这么多手写的seralization代码,我想摆脱OR-Mapper。这样做的原因是我可以更轻松地创建迁移器,它可以读取旧的JSON格式并执行必要的迁移步骤(添加数据,忽略不再需要的数据等)。使用OR-Mapper,我需要旧类型来解析旧格式,然后将旧类型转换为新类型 - 这是一种有效的策略,但由于我有手写代码,我可以执行非常精细的粒度迁移步骤并做出反应几乎任何变化。 基本上更强大,我不需要旧的对象模型。

2)那么实际问题是什么?

我是否可以使用protobuf-net或多或少手动从/向流中读取/写入数据 以某种其他方式对(反)序列化具有相似的能力(例如RuntimeTypeModel?)

使用上面的例子:

  • 我有一个类型为MetaType的属性的对象,但我不想序列化整个MetaType,而只想存储字符串或ID。反序列化时,字符串或ID用于获取正确的MetaType(< =我只需要解析器来存储/读取ID,我会进行查找)
  • 我希望能够在序列化上过滤集合,并且只存储符合特定条件的对象。
  • 我希望能够通过阅读它们并根据需要迁移数据来支持旧格式。 我已经存储了一个版本号,可用于分支反序列化或创建不同类型的对象(v1,v2) - 但如果我不需要使用多个,我更喜欢它我的对象模型的版本,在解析器级别(在创建对象之前)进行迁移会很棒。

伪代码示例(如果上述情况没有意义):

int version = Reader.ReadInt()
// [...] decide how to proceed based on version
var typeName = Reader.ReadString()
var type = MetaType.For(typeName)
// [...] read some more properties
return new ValueObject(type, property1, property2)

与protobuf-net有类似的可能性/推荐吗? (示例/链接到文档或教程会很棒 - 我知道有一个ProtoReader类,但我不确定我是否应该使用它/如果我足够聪明,可以在没有任何文档的情况下使用它)

修改
在此处添加Marc的评论以获得更好的可见性:

可以找到ProtoReader / ProtoWriter的原始用法示例 here direct link to code)。

1 个答案:

答案 0 :(得分:1)

大部分都是可能的。在最新的级别,ProtoReader有一个完整的API来读取底层流。如果你知道你只想阅读"字段1作为预期" (对于版本等)你可以设置一个模型,并让图书馆完成繁重的工作:

[ProtoContract] class VersionStub {
    [ProtoMember(1)] public int Version {get;set;}
}

如果您有多个相同型号的不兼容版本,则可以单独创建和使用不同的RuntimeTypeModel实例(您应该尽可能缓存并重用模型以获得性能)。

但是,API基于预先存在的具体类型 - 它允许您在运行时配置地图,但它当前不会动态创建DTO类型。它可能。虽然 - 它已经有足够的内置元编程......

我回答了这个问题吗?还是另一个?