Protobuf:扩展注册表问题

时间:2014-02-13 07:01:25

标签: java protocol-buffers

我试图在protobuf中使用类型继承,这是通过扩展机制实现的。问题是我必须将一个额外的参数传递给序列化器/反序列化器才能使其正常工作:

ExtensionRegistry registry = ExtensionRegistry.newInstance();
Animals.registerAllExtensions(registry);
Zoo newZoo = Zoo.parseFrom(buf, registry);

另一个问题是我使用内置了protobuf的第三方库(RPC),所以我无法控制代码中的序列化/反序列化。

有没有办法在全球范围内注册扩展程序?

P.S。我的问题原型:

message Zoo {
  repeated Animal animals = 1;
}

message Animal
{
    extensions 100 to max;

    enum Type
    {
        Cat = 1;
        Dog = 2;
    }

    required Type type = 1;
}

message Cat
{
    extend Animal
    {
        required Cat animal = 100; // Unique Animal extension number
    }

    // These fields can use the full number range.
    optional bool declawed = 1;
}

message Dog
{
    extend Animal
    {
        required Dog animal = 101; // Unique Animal extension number
    }

    // These fields can use the full number range.
    optional uint32 bones_buried = 1;
}

1 个答案:

答案 0 :(得分:1)

不,没有办法全局注册扩展。您的RPC库应该允许您指定ExtensionRegistry - 如果没有,那么这是库中的一个严重问题。您可以通过序列化您收到的消息对象来解决它,然后使用ExtensionRegistry重新解析它,尽管这当然会浪费CPU时间。

编辑:无法在全球注册的原因是全球注册管理机构往往会导致许多微妙的问题。他们基本上是单身人士,并且singletons are bad的所有常见原因都不好。本质上,代码可能会意外地依赖于同一进程中不相关代码段的实现细节,从而损害模块性和可重用性。例如,服务器中的某些代码可能无意中依赖于其他一些不相关的代码来为它们注册扩展,然后当其他代码更改或删除时,第一段代码意外地中断了一个奇怪的,微妙的方式 - 突然之间,好像所需的扩展名从未出现在收到的消息中。 protobuf C ++库实际上有一个全局扩展注册表,我们在实践中看到了很多这类问题,所以在这之间以及Java类无法强制某些代码在“启动时”运行的事实(静态初始化发生在懒惰中) ,这使得更难确保在正确的时间进行注册),我认为最好完全避免全局注册。当然,正如你所见,这个决定有其自身的问题......似乎这里没有正确的答案。 :(