1、概念
Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。
将 程序数据转化成能被存储并传输的格式的过程被称为“序列化”(Serialization),而它的逆过程则可被称为“反序列化” (Deserialization)。
简单来说,序列化就是将对象实例的状态转换为可保持或传输的格式的过程。与序列化相对的是反序列化,它根据流重构对象。这两个过程结合起来,可以轻 松地存储和传输数据。
序列化:将对象变成字节流的形式传出去。 反序列化:从字节流恢复成原来的对象。
protobuf的反射功能
-
Message:Person是自定义的pb类型,继承自Message. MessageLite作为Message基类,更加轻量级一些。
通过Message的两个接口GetDescriptor/GetReflection
,可以获取该类型对应的Descriptor/Reflection。 -
Descriptor:Descriptor是对message类型定义的描述,包括message的名字、所有字段的描述、原始的proto文件内容等,提供的接口:获取所有字段的个数:
int field_count() const
获取单个字段描述类型FieldDescriptor
的接口。
-
FieldDescriptor:描述message中的单个字段,例如字段名,字段属性(optional/required/repeated)等。
-
Reflection:提供了动态读写pb字段的接口,对pb对象的自动读写主要通过该类完成。对每种类型,Reflection都提供了一个单独的接口用于读写字段对应的值。
//读操作
virtual int32 GetInt32 (const Message& message,const FieldDescriptor* field) const = 0;
virtual int64 GetInt64 (const Message& message,const FieldDescriptor* field) const = 0;
//对于枚举和嵌套的message
virtual const EnumValueDescriptor* GetEnum(const Message& message, const FieldDescriptor* field) const = 0;
virtual const Message& GetMessage(const Message& message,const FieldDescriptor* field,MessageFactory* factory = NULL) const = 0;
反射使用
- 通过类型名创建类型对象
// 先获得类型的Descriptor .
auto descriptor = google::protobuf::DescriptorPool::generated_pool()->FindMessageTypeByName("T.Test");
if (nullptr == descriptor)
{
return 0 ;
}
// 利用Descriptor拿到类型注册的instance. 这个是不可修改的.
auto prototype = google::protobuf::MessageFactory::generated_factory()->GetPrototype(descriptor);
if ( nullptr == descriptor)
{
return 0 ;
}
// 构造一个可用的消息.
auto message = prototype->New();
// 只有当我们预先编译了test消息并且正确链接才能这么干.
auto test = dynamic_cast<T::Test*>(message);
// 直接调用message的具体接口
// 其实这些接口是语法糖接口.所以并没有对应的反射机制来对应调用.
// 反射机制实现了的Set/Get XXX系列接口,是属于Reflection的接口,接收Message作为参数.
test->set_id(1);
- 通过对象和对象的属性的名字获取、修改对应的属性
// 拿到一个对象,不在乎怎么拿到,可以是通过反射拿到。
// 这里简单直接的创建一个.
T::Test p_test ;
// 拿到对象的描述包.
auto descriptor = p_test.GetDescriptor() ;
// 拿到对象的反射配置.
auto reflecter = p_test.GetReflection() ;
// 拿到属性的描述包.
auto field = descriptor->FindFieldByName("id");
// 设置属性的值.
reflecter->SetInt32(&p_test , field , 5 ) ;
// 获取属性的值.
std::cout<<reflecter->GetInt32(p_test , field)<< std::endl