protobuf是google的一個開源項目,可用於如下兩種用途:git
(1)數據的存儲(序列化和反序列化),相似於xml、json等;github
(2)製做網絡通訊協議。json
源代碼下載地址:https://github.com/mgravell/protobuf-net數組
開源項目地址以下:https://code.google.com/p/protobuf-net/,下載解壓後的目錄以下所示,每一個文件夾的詳細介紹都在最後一個txt文件裏面了。網絡
ProtoGen是用來根據***.proto文件生成對應的***.cs文件的,而作數據存儲功能只須要用到protobuf-net.dll便可,至於使用哪一個版本項目狀況決定。下面的例子在Windows平臺下新建一個C#的控制檯工程,並引入ProtoBufNet\Full\net30\protobuf-net.dll,代碼以下所示:ui
namespace TestProtoBuf { [ProtoContract] public class Address { [ProtoMember(1)] public string Line1; [ProtoMember(2)] public string Line2; } [ProtoContract] public class Person { [ProtoMember(1)] public int Id; [ProtoMember(2)] public string Name; [ProtoMember(3)] public Address Addr; } class Program { static void Main(string[] args) { Person person = new Person(); person.Id = 1; person.Name = "First"; person.Addr = new Address { Line1="line1", Line2="line2"}; // ProtoBuf序列化 using(var file = System.IO.File.Create("Person.bin")) { ProtoBuf.Serializer.Serialize(file, person); } // ProtoBuf反序列化 Person binPerson = null; using(var file = System.IO.File.OpenRead("Person.bin")) { binPerson = ProtoBuf.Serializer.Deserialize<Person>(file); } System.Console.WriteLine(binPerson.Name); } } }
能夠看到序列化和反序列化的代碼很是簡單。this
protobuf提供了一種proto腳本用來編寫***.proto文件,這種腳本格式簡單、可讀性強、方便擴展,用proto腳本定義網絡協議是很是好用的。google
下面是一個proto腳本的簡單例子:spa
message Person { required string name=1; required int32 id=2; 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; }
requied是必須有的字段、optional是無關緊要的字段、repeated是能夠重複的字段(數組或列表),同時枚舉字段都必須給出默認值。命令行
接下來就能夠使用ProgoGen來根據proto腳本生成源代碼cs文件了,命令行以下:
protogen -i:test.proto -0:test.cs -ns:MyProtoBuf
-i指定了輸入,-o指定了輸出,-ns指定了生成代碼的namespace,上面的proto腳本生成的源碼以下:
//------------------------------------------------------------------------------ // <auto-generated> // This code was generated by a tool. // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // </auto-generated> //------------------------------------------------------------------------------ // Generated from: file/pb.proto namespace MyProtoBuf { [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"Person")] public partial class Person : global::ProtoBuf.IExtensible { public Person() {} private string _name; [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"name", DataFormat = global::ProtoBuf.DataFormat.Default)] public string name { get { return _name; } set { _name = value; } } private int _id; [global::ProtoBuf.ProtoMember(2, IsRequired = true, Name=@"id", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] public int id { get { return _id; } set { _id = value; } } private string _email = ""; [global::ProtoBuf.ProtoMember(3, IsRequired = false, Name=@"email", DataFormat = global::ProtoBuf.DataFormat.Default)] [global::System.ComponentModel.DefaultValue("")] public string email { get { return _email; } set { _email = value; } } private readonly global::System.Collections.Generic.List<Person.PhoneNumber> _phone = new global::System.Collections.Generic.List<Person.PhoneNumber>(); [global::ProtoBuf.ProtoMember(4, Name=@"phone", DataFormat = global::ProtoBuf.DataFormat.Default)] public global::System.Collections.Generic.List<Person.PhoneNumber> phone { get { return _phone; } } [global::System.Serializable, global::ProtoBuf.ProtoContract(Name=@"PhoneNumber")] public partial class PhoneNumber : global::ProtoBuf.IExtensible { public PhoneNumber() {} private string _number; [global::ProtoBuf.ProtoMember(1, IsRequired = true, Name=@"number", DataFormat = global::ProtoBuf.DataFormat.Default)] public string number { get { return _number; } set { _number = value; } } private Person.PhoneType _type = Person.PhoneType.HOME; [global::ProtoBuf.ProtoMember(2, IsRequired = false, Name=@"type", DataFormat = global::ProtoBuf.DataFormat.TwosComplement)] [global::System.ComponentModel.DefaultValue(Person.PhoneType.HOME)] public Person.PhoneType type { get { return _type; } set { _type = value; } } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } [global::ProtoBuf.ProtoContract(Name=@"PhoneType")] public enum PhoneType { [global::ProtoBuf.ProtoEnum(Name=@"MOBILE", Value=0)] MOBILE = 0, [global::ProtoBuf.ProtoEnum(Name=@"HOME", Value=1)] HOME = 1, [global::ProtoBuf.ProtoEnum(Name=@"WORK", Value=2)] WORK = 2 } private global::ProtoBuf.IExtension extensionObject; global::ProtoBuf.IExtension global::ProtoBuf.IExtensible.GetExtensionObject(bool createIfMissing) { return global::ProtoBuf.Extensible.GetExtensionObject(ref extensionObject, createIfMissing); } } }
to be continue...