Google Protobuf擴展字段使用

背景說明

Google Protobuf中不支持數據結構的派生關係,所以,若是在存在派生體系的對象中定義數據結構時,經過組合方式對數據結構進行組合,則須要對基類對象提供的通用接口進行重載或在外部進行動態轉型才能達到獲取或設置數據的目的。數據結構

所以考慮使用Google Protobuf提供的extension擴展機制解決數據結構之間的不能派生的問題,以此來達到減小重複工做量和便於維護代碼的目的。ide

使用說明

  1. 定義公共數據類型

    描述:ui

    此數據類型爲對象派生體系同基類提供的公共數據類型spa

    示例:code

     
    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. 定義擴展數據類型

    描述:對象

    此數據類型爲對象派生體系中派生類使用的數據類型blog

    示例:接口

     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. 初始化數據類型

    描述:string

    公共數據類型與普通數據類型使用相同,此處僅說明擴展數據類型使用方法io

    示例:

     
     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
相關文章
相關標籤/搜索