protobuf-net


  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); }
  }
  
}

*********************分割線*********************

最近又玩了一下pbnet,發現pbnet的github工程里面提供了各個版本的protobuf-net的版本,而且需要自己來編譯:
     
    protobuf-net的實現沒有依賴任何.net 4.0的特性, 所以net30版本就能提供完整的功能
    net30和net20版本唯一的區別:net30支持wcf
    每個版本里面包含三個文件:
        protobuf-net.dll:庫文件,需要放到應用工程里面的
        protobuf-net.xml:IDE使用的配置
        protobuf-net.pdb:deug時使用的symblos,用來定位崩潰之類的問題 
 
版本
說明
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 
代碼生成工具還是和以前一樣:
    shell sample:
    目錄下的每個proto生成對應的cs文件:
    FOR /R %%G IN (*.proto) DO ..\ProtoBuf\protogen.exe -i:%%G -o:%%~nG_pb.cs 

    其中ns用來設置namespace,只有在proto里面沒有指定namespace才會生效。 
 
不過,proto3.0目前已知支持c#了,所以就可以直接使用官方版本了:
  (1)使用源碼來編譯生成Google.Protobuf.dll;
  (2)使用protoc3分析proto生成對應的c#代碼。
  protoc3生成c#代碼的語法,和之前pbnet略有不同:
     protoc3 -I=ProtoDir --csharp_out=CSDir ProtoFileName.proto
  說明:
        ProtoDir為proto定義的目錄;
        CSDir為生成的對應的***.cs的文件目錄;
        ProtoFileName.proto就是要生成的proto文件名 。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM