protobuf是google的一個開源項目,可用於以下兩種用途:
(1)數據的存儲(序列化和反序列化),類似於xml、json等;
(2)制作網絡通信協議。
源代碼下載地址: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,代碼如下所示:
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); } } }
可以看到序列化和反序列化的代碼非常簡單。
protobuf提供了一種proto腳本用來編寫***.proto文件,這種腳本格式簡單、可讀性強、方便擴展,用proto腳本定義網絡協議是非常好用的。
下面是一個proto腳本的簡單例子:
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); } } }
*********************分割線*********************
版本
|
說明
|
net20 | regular .NET 2.0 (excludes WCF hooks) |
net30 | regular .NET 3.0 or above (including 3.5, 4.0, 4.5, ...) |
netcore45 | windows store apps / windows runtime 4.5 |
sl4 | silverlight 4 or above |