1

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

(跳到第2 点)问题,1)只是提供一些上下文)

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

我目前在我的项目中使用 JSON.Net,并创建了几个 JSONConverter 来自定义各种类型的序列化方式——基本上所有主要类型都有手写的序列化指令(ReadProperty、ReadValue 等)。

我为什么这样做以及在哪里这样做的一些例子:

  • 我有一个MetaType类来描述某些Value对象在运行时的行为。这些Value对象有一个Type被序列化的属性。一个ConverterMetaType在序列化这个属性时只返回该属性的名称,反序列化时使用该名称获取对应MetaType的inf。这样做的原因是类型的名字就够了,MetaType类序列化太麻烦,生成的JSON更紧凑。
  • 一些对象的集合包含不需要序列化的值,因为我可以根据MetaType它们不存在的时间重新创建它们。转换器过滤这些集合并仅存储那些不是默认值的值 - 而 JSON.Net 具有防止属性在设置为默认值时被序列化的属性,我不知道任何内置方法来过滤默认值从一个集合。

我的目标是什么:

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

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

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

要使用上面的示例:

  • 我有一个具有 type 属性的对象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

4

1 回答 1

1

大部分是可能的。在最原始的层面上,ProtoReader 具有用于读取底层流的完整 API。如果您知道您只想阅读“预期的字段 1”(对于版本等),您可以设置一个模型并让库完成繁重的工作:

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

如果您有同一模型的多个不兼容版本,则可以单独创建和使用不同的 RuntimeTypeModel 实例(您仍应尽可能缓存和重用模型以提高性能)。

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

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

于 2013-02-26T18:33:32.547 回答