2

我正在从运行时加载DynamicMessage的文件中构建java 。.proto

我的问题是设置此类消息的扩展名。

我有:

  • Descriptors.Descriptor包含类型并DynamicMessage为其创建
  • Descriptors.Descriptor扩展类型并DynamicMessage为其创建

现在我不知道如何将扩展名设置为包含的消息。

如果我要求字段列表,包含描述符仅列出扩展名中没有字段的字段。这是有道理的。

扩展描述符只有扩展类型的字段(它没有包含类型的字段)。

请建议我如何将这些结合在一起。

要了解上下文,您可能需要查看我之前关于此主题的不关心扩展的问题:运行时生成的协议缓冲区对象

编辑:

事实上,我正在寻找.setExtension生成消息的类比。我注意到只有GeneratedMessage扩展ExtendableMessage,但我相信一定有办法:)

4

2 回答 2

6

扩展由FieldDescriptors 描述,就像常规字段一样,因此在使用动态接口时,您实际上使用完全相同的方法来访问任一接口。

请记住,扩展实际上是独立于扩展类型或扩展类型声明的。例如,这是有效的:

message Foo { extensions 1000 to max; }
message Bar { ... }
extend Foo {
  optional Bar ext1 = 1234;
  optional Bar ext2 = 2345;
}

请注意,我们声明了对 type 的两个扩展。因此,仅仅知道您正在寻找类型的扩展是不够的——您必须指定哪一个。FooBarBar

在任何情况下,各种描述符类型都喜欢FileDescriptorDescriptor具有findExtensionByName()可用于查找扩展描述符的方法。请注意,此方法查找在您调用它的描述符范围内声明的扩展——它找不到该消息类型的扩展。也就是说,如果您有:

message Foo { extensions 1000 to max; }
message Bar {
  extend Foo {
    optional int32 ext1 = 1234;
  }
}
extend Foo {
    optional int32 ext2 = 2345;
}

为了找到扩展ext1,您必须调用findExtensionByName("ext1")for DescriptorBar不是描述符Foo。要查找ext2,您必须调用findExtensionByName("ext2")文件的FileDescriptor.

您可能还想查看ExtensionRegistry该类,它可用于通过其完全限定名称(例如"mypackage.Bar.ext1")查找扩展,但这需要您首先注册您感兴趣的描述符,因此它可能不是非常有帮助。

于 2013-09-28T02:09:19.647 回答
0

我还试图在 C++ 中找到解决方案,使用以下代码似乎更容易:

const Reflection* reflection = merged_doc_info.GetReflection();<br/>
const FieldDescriptor * ext_fld=reflection->FindKnownExtensionByName("msg.usage");
assert(ext_fld!=0);
reflection->SetUInt32(&merged_doc_info,ext_fld,123);

另一种方法是模拟 protoc 命令的作用,生成 java 代码行,例如

msgBuilder.setExtension(msg.usage, "1"); 
于 2013-12-03T07:06:46.577 回答