【发布时间】:2015-03-11 07:55:00
【问题描述】:
我正在使用协议缓冲区的反射功能在运行时读取消息字段值。
我拥有的原型:
package xapp.battle;
message BATTLE_DATA {
repeated AInfo aInfo = 1;
repeated BInfo bInfo = 2;
repeated CInfo cInfo = 3;
// a lot other repeated messages
}
message AInfo {
int32 test_field = 1;
// ......
}
message BInfo {
int32 test_field = 1;
// ......
}
message CInfo {
int32 test_field = 1;
// ......
}
我现在拥有的代码:
void DO_SOMETHING(messageName) {
const Descriptor* pDescriptor = BATTLE_DATA->GetDescriptor();
const FieldDescriptor* pMessageField = pDescriptor->FindFieldByName(messageName);
const Reflection* pReflection = BATTLE_DATA->GetReflection();
if (messageName == "aInfo") {
const RepeatedPtrField<::xapp::battle::AInfo> repeated_ptr_field = pReflection->GetRepeatedPtrField<::xapp::battle::AInfo>(*BATTLE_DATA, pMessageField);
for (int i = 0; i < repeated_ptr_field.size(); i ++) {
::xapp::battle::AInfo messageInfo = repeated_ptr_field.Get(i);
// continue to read the test_field value of messageInfo
}
}
else if (messageName == "bInfo") {
const RepeatedPtrField<::xapp::battle::BInfo> repeated_ptr_field = pReflection->GetRepeatedPtrField<::xapp::battle::BInfo>(*BATTLE_DATA, pMessageField);
for (int i = 0; i < repeated_ptr_field.size(); i ++) {
::xapp::battle::BInfo messageInfo = repeated_ptr_field.Get(i);
// continue to read the test_field value of messageInfo
}
}
else if (messageName == "CInfo") {
const RepeatedPtrField<::xapp::battle::CInfo> repeated_ptr_field = pReflection->GetRepeatedPtrField<::xapp::battle::CInfo>(*BATTLE_DATA, pMessageField);
for (int i = 0; i < repeated_ptr_field.size(); i ++) {
::xapp::battle::CInfo messageInfo = repeated_ptr_field.Get(i);
// continue to read the test_field value of messageInfo
}
}
// ......
else {
LOG("loadOneBin - Unknown messageName");
}
}
此代码有效,但显然它不是最佳解决方案,因为有太多重复的“else-if”代码块。
我想要的是(至少摆脱那些“else-if”块):
const RepeatedPtrField<::xapp::battle::MESSAGE_NAME> repeated_ptr_field = pReflection->GetRepeatedPtrField<::xapp::battle::MESSAGE_NAME>(*BATTLE_DATA, pMessageField);
for (int i = 0; i < repeated_ptr_field.size(); i ++) {
::xapp::battle::MESSAGE_NAME messageInfo = repeated_ptr_field.Get(i);
// continue to read the test_field value of messageInfo
}
GetRepeatedPtrField的源码:
template<typename PB>
inline const RepeatedPtrField<PB>& Reflection::GetRepeatedPtrField(
const Message& message, const FieldDescriptor* field) const {
return *static_cast<RepeatedPtrField<PB>* >(
MutableRawRepeatedField(const_cast<Message*>(&message), field,
FieldDescriptor::CPPTYPE_MESSAGE, -1,
PB::default_instance().GetDescriptor()));
}
任何建议将不胜感激,谢谢:)
【问题讨论】:
标签: c++ templates reflection protocol-buffers