Google Protobuf扩展字段使用

背景说明

Google Protobuf中不支持数据结构的派生关系,因此,如果在存在派生体系的对象中定义数据结构时,通过组合方式对数据结构进行组合,则需要对基类对象提供的通用接口进行重载或在外部进行动态转型才能达到获取或设置数据的目的。

因此考虑使用Google Protobuf提供的extension扩展机制解决数据结构之间的不能派生的问题,以此来达到减少重复工作量和便于维护代码的目的。

使用说明

  1. 定义公共数据类型

    描述:

    此数据类型为对象派生体系同基类提供的公共数据类型

    示例:

     
    1 // 公共数据类型
    2 message BaseDataType
    3 {
    4     extensions 100 to max;   //标识此字段可扩展,此处可指定扩展字段的ID有效范围,to max表示字段范围至最大值
    5     optional string BaseField1 = 1;
    6     optional string BaseField2= 2;
    7     ...
    8 } 
    View Code
  2. 定义扩展数据类型

    描述:

    此数据类型为对象派生体系中派生类使用的数据类型

    示例:

     1 message ChildDataType
     2 {
     3     extend BaseDataType
     4     {
     5         optional ChildDataType ChildData = 100;     // 将子数据类型整体扩展至公共数据中
     6         optional int32  ExtendValue = 101;          // 扩展具体数据类型
     7     }
     8     optional string ChildField1 = 1;
     9     optional string ChildField2= 2;
    10     ...
    11 } 
    View Code
     
  3. 初始化数据类型

    描述:

    公共数据类型与普通数据类型使用相同,此处仅说明扩展数据类型使用方法

    示例:

     
     1 // 对象基类
     2 class BaseClass
     3 {
     4     public BaseClass()
     5     {
     6          m_pData = new BaseDataType();
     7     }
     8 public:
     9     Message* m_pData;
    10 };
    11  
    12 // 对象派生类
    13 class ChildClass : public BaseClass
    14 {
    15     public ChildClass ()
    16     {
    17         BaseDataType * pBaseData = new BaseDataType();
    18         // 创建爱你扩展数据类型
    19         ChildDataType* pChildData = pBaseData->MutableExtension(ChildDataType::ChildData);
    20         //初始化数据
    21         pChildData-> set_childfield1("123");
    22         pBaseData->SetExtension(ChildDataType::ExtendValue, 123);
    23     }
    24 }; 
    View Code
  4. 使用数据类型

    描述:

    通过HasExtension、GetExtension、MutableExtension来访问数据;

    示例:

    1 // 构造对象访问扩展数据类型数据
    2 BaseClass* pBaseObj = new ChildClass();
    3 BaseDataType* pBaseData = dynamic_cast<BaseDataType*>(pBaseObj->m_pData);
    4 assert(pBaseData->HasExtension(ChildDataType::ChildData));
    5 // 获取扩展数据
    6 const ChildDataType& childdata = pBaseData->GetExtension(ChildDataType::ChildData);
    7 int value = pBaseData->GetExtension(ChildDataType::ExtendValue); 
    View Code
  5. 数据复制及传输

    描述:

    C++代码中数据复制及传输解析与普通数据类型相同,此处仅说明C#代码中需要注意事项。

    C#中通过ParseFrom进行字节数据转换时,需要传入对扩展数据结构的说明信息ExtensionRegistry,否则扩展数据字段将作为未知数据处理。

    示例:

     1 // 构造扩展数据类型
     2 ChildDataType.Builder childdata = new ChildDataType.Builder();
     3 childdata.ChildField1 = "123";
     4 // 构造公共数据类型
     5 BaseDataType.Builder basedata = new BaseDataType.Builder();
     6 basedata.SetExtension(ChildDataType.ChildData,
     7 childdata.Build());
     8  
     9 // 转换至字节数据数据
    10 byte[] buf = basedata.Build().ToByteArray();
    11  
    12 // 创建扩展字段信息
    13 ExtensionRegistry registry = ExtensionRegistry.CreateInstance();
    14 registry.Add(ChildDataType.ChildData);
    15 registry.Add(ChildDataType.ExtendValue);
    16  
    17 // 从字节数据转换
    18 BaseDataType basedataCopy = BaseDataType.ParseFrom(buf, registry);
    19 System.Diagnostics.Debug.Assert(basedataCopy.HasExtension(ChildDataType.ChildData)); 
    View Code
原文地址:https://www.cnblogs.com/rain2012qf/p/4241020.html