Protocol Buffers (下面簡稱PB)是一種輕便高效的結構化數據存儲格式,能夠用於結構化數據串行化,很適合作數據存儲或 RPC 數據交換格式。它可用於通信協議、數據存儲等領域的語言無關、平臺無關、可擴展的序列化結構數據格式。它支持多種語言,好比C++,Java,C#,Python,JavaScript等等。目前它的最新版本是3.0.0。與PB常常相提並論的也是Google推出的FlatBuffers(下面簡稱FB)。有關PB和FB性能和語義等方面的區別,這裏就不展開描述了。若是有興趣,能夠參閱下面的信息:html
目前不少公司在一些高性能的通訊場景下,會愈來愈多的選擇用PB或者FB來替代咱們經常使用的Json。好比說Windows Phone的微信的SDK就用到了。linux
PB對C#官方的支持是從3.0開始的,以前的1.0和2.0的版本都能找到一些非官方的版本。咱們先反編譯一下微信的SDK,看下它具體是什麼版本的。git
首先,咱們從微信的官網下載SDK:github
登錄微信開發平臺,進入資源中心,選擇WP8資源下載,點擊下載。微信
而後下載咱們的反編譯工具ILSpy。微信開發
解壓下載完成的ILSpy和SDK包,用ILSpy.exe打開MicroMsgSDK.dll。工具
咱們暫時先無論這個結構究竟是怎麼來的,咱們能夠看到反編譯出來的文件帶了ProtoGen的版本號,咱們嘗試從Github上找到這個版本號的代碼。性能
咱們先打開官方的C#版本的PB的源碼頁面:地址。ui
能夠看到官方地址只保留了3.0的版本,對於舊的2.0版本的代碼在jskeet的帳號下,this
咱們點開這個倉庫,而後找到它的Release頁面:
咱們找到2.3.0.277的源碼並下載到本地。
解壓文件,咱們看到Build文件夾下有一堆編譯用的腳本:
雙擊運行buildAll.bat(此處應確保本機已經安裝了Visual Studio 2008及以上版本),而後等待編譯完成。
咱們找到ProtoGen項目中生成的exe文件,嘗試將它放到命令行中運行:
它提示咱們找不到protoc.exe程序。咱們回到源碼的根目錄會發現有一個lib的文件夾,裏面有一個protoc.exe的程序。因此咱們嘗試吧ProtoGen項目的全部生成文件拷貝到lib下。
繼續嘗試運行咱們的ProtoGen程序。
這回對了,咱們嘗試把源碼下的protos文件夾下的三個子文件夾拷貝到咱們的lib目錄下。
咱們嘗試輸入以下內容:
protogen --proto_path==protos protos/tutorial/addressbook.proto
又獲得一個錯誤信息:
提示咱們找不到依賴,咱們嘗試打開proto文件:(有關PB的語法請參閱:http://www.cnblogs.com/stephen-liu74/archive/2013/01/02/2841485.html)
package tutorial; import "google/protobuf/csharp_options.proto"; option (google.protobuf.csharp_file_options).namespace = "Google.ProtocolBuffers.Examples.AddressBook"; option (google.protobuf.csharp_file_options).umbrella_classname = "AddressBookProtos"; option optimize_for = SPEED; message Person { required string name = 1; required int32 id = 2; // Unique ID number for this person. optional string email = 3; enum PhoneType { MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; } // Our address book file is just one of these. message AddressBook { repeated Person person = 1; }
咱們能夠看到導入了google/protobuf/csharp_options.proto文件,咱們回頭看protogen的命令參數中有一個import的標記,咱們嘗試添加:
protogen --proto_path==protos protos/tutorial/addressbook.proto --include_imports=google/protobuf/csharp_options.proto
沒有任何錯誤,而且咱們在lib的目錄下發現了生成的cs文件。
咱們打開AddressBookProtos文件,閱讀源碼發現:
只有兩個非靜態類,與咱們Proto文件中的Person和AddressBook對應:
Person類中又有一個嵌套的枚舉和類,與PhoneType和PhoneNumber對應:
咱們有發現,在類的IsInitialized中,Name和Id等required的有是否有值得判斷,因此咱們能區分去required和optional
其餘依賴信息,咱們能夠經過引用來查找。
咱們以BaseReqP爲例。首先,沒有using,因此咱們肯定沒有其餘的Proto文件的依賴。咱們只發現一個類,因此說明它只有一條message,名稱就是BaseReqP,而後包名是MicroMsg.sdk.protobuf。
咱們知道message的全部字段是須要標記數字的:
從這裏咱們又反推出,message有兩個字段:Transaction和Type,它們類型分別是string和uint。
接下來咱們推是不是必須的。找到咱們的IsInitialized:
從這裏咱們就知道了兩個字段都是必須的。因此綜合上述信息,咱們能夠寫出的proto文件以下:
package MicroMsg.sdk.protobuf; message BaseReqP { required uint32 Type = 1; required string Transaction = 2; }
本篇內容簡要介紹了ProtoBuffer的文件如何生成C#文件,並簡單的舉例如何從C#文件反推Proto文件。