【发布时间】:2020-08-03 22:12:02
【问题描述】:
我想知道是否有一种通用的方法来反序列化具有oneof 子消息的消息。 oneof 消息将包含许多其他消息。现在,我可以在case 号码上使用switch 声明并调用适当的getter 来让它工作。但是,如果有一个通用的方法,那么将来我就不必继续添加新的案例了。
我想消除这些情况并有一些通用的东西,我可以在其中获取消息类型,即 Exit 并调用正确的 getter。有没有办法通过反射来做到这一点?我在网上找了一些例子,但找不到太多。
原型文件:
message AllClientMessages {
oneof client_message {
util.client.command Exit exit = 1
util.client.command SendNew sendnew = 2
util.client.command CancelAll cancelAll = 3
// ... (more than 60 messages)
}
}
代码(buf 包含序列化消息):
const std::unique_ptr<google::protobuf::Message> ProtoBuilder::deserialize(char* buf)
{
AllClientMessages clientMsg;
clientMsg.ParseFromString(buf);
switch(clientMsg.client_message_case())
{
case AllClientMessages::kExitFieldNumber: //generate enums
return make_unique<Exit>(clientMsg.exit());
case AllClientMessages::kSendNewFieldNumber:
return make_unique<SendNew>(clientMsg.sendnew());
// I access the getter and return unique_ptr to base protobuf Message.
// ... I do this for each case.
}
}
【问题讨论】:
-
顺便说一句,您应该在继续使用解析的消息之前测试
ParseFromString()的返回值(布尔值),即if ( !clientMsg.ParseFromString(buf) ) { /* handle_error_here */ }。 -
另一个关于 ParseFromString(buf) 的问题。 :它还会填充 oneof 消息吗?还是我也需要在 oneof 对象上调用 ParseFromString 。我正在获取默认值。
-
二进制消息将被反序列化,结果将是填充的消息对象。如果它是消息的一部分,它应该被自动反序列化。 问题:您为什么使用oneof?看起来应该是enum。示例:godbolt.org/z/rnnx8x.
-
知道了。我看到
oneof为您提供了某种自动化枚举和对象处理设施。建议:您应该使用Generated Code 文章中描述的默认值(索引零),以便在未正确设置消息的情况下使错误处理更加稳健。
标签: c++ generics reflection protocol-buffers