使用协议缓冲区模拟泛型

Posted

技术标签:

【中文标题】使用协议缓冲区模拟泛型【英文标题】:simulate generics with protocol buffer 【发布时间】:2014-09-21 09:17:01 【问题描述】:

我有一个存储和操作一些实体的类。根据输入的数量,我可能无法将实体存储在内存中,因此我尝试使用协议缓冲区序列化要写入硬盘的对象。我正在使用 C# 和 protobuf-csharp-port。我知道protobuf-net 作为替代端口;到目前为止,我一直在使用第一个选项,但如果需要根据我的需要进行更改,我愿意进行更改。

要序列化的类的简化形式如下:

class Entity<T> where T: IComparable<T>

    int id;
    T metaData;

所以在编译时我对metaData 没有任何线索。谷歌搜索我注意到扩展是正确的路径(如google's page和this question所建议的那样);因此我为Entity 类定义Entity.proto 文件如下:

message Entity

    required int32 id = 1 [default = 0];
    extensions 2 to max; 

我希望用户为T 提供他自己的.proto 文件,而无需访问或重新编译Entity.proto。在这方面,我的问题是:

    我需要更改Entity.proto 吗? T.proto 应该是什么? 如何在我的 C# 代码中访问 T

【问题讨论】:

【参考方案1】:

使用该方案,任何扩展都将是非泛型Entity子值(不是子类)。这听起来不像是泛型,但最终存储(序列化)通常与实现完全不同(Entity&lt;T&gt; 等)。如果您可以在它们之间手动映射:很好。但这不是图书馆将提供的东西,AFAIK。

为了完整性,在 protobuf-net 术语中:使用 Entity&lt;T&gt; 完全没问题 - 它本质上认为每个(Entity&lt;Foo&gt;Entity&lt;Bar&gt; 等)都是完全独立的消息。 Protobuf-net 并没有受到 .proto 模式的极大推动(尽管为了完整性提供了代码生成工具)——它主要使用运行时元数据。

【讨论】:

如果我错了请纠正我:protobuf-net 支持泛型,然后我可以使用Entity&lt;T&gt; 编译我的库,它是序列化程序 (1)。使用该库时,T 用户还将提供它的序列化程序 (2)。最终,Entity&lt;T&gt; 的实例将使用 (1) 和 (2) 进行序列化。 @hamed 在使用 protobuf-net 时最常见,您根本不分发序列化程序:库会在需要时担心这一点。您分发序列化程序的主要时间是针对 AOT 设备 可能与 OOP 混合太多,但我完全糊涂了。 Entity 不知道 T 所以它不能序列化它。另一方面,T 不知道Entity 的数据结构,所以它也不能提供序列化。那我想知道Entity&lt;Foo&gt;是怎么序列化的? @Hamed 因为Entity&lt;&gt;T 都不负责序列化。 library 是 - 它看到的只是封闭的泛型类型Entity&lt;Foo&gt;。坦率地说,它甚至都懒得去检查它是否通用的——因为那根本不重要。 这解释了。之所以提出疑问,是因为我试图解释 .proto 方案中的所有内容,其中 Entity&lt;T&gt; proto 在库构建时生成和编译,T proto 生成并连接到它。

以上是关于使用协议缓冲区模拟泛型的主要内容,如果未能解决你的问题,请参考以下文章

使用协议缓冲区的 Android Http 请求和响应

在没有它们的情况下解析协议缓冲区数据

如何在 autoconf/automake 中使用协议缓冲区?

使用协议缓冲区和内部数据模型

在 Windows 中使用 MinGW 的 Google 协议缓冲区

如何使用协议缓冲区创建动态消息?