protobuf-net

  protobuf是google的一个开源项目,可用于以下两种用途:

  (1)数据的存储(序列化和反序列化),类似于xml、json等;

  (2)制作网络通信协议。

  源代码下载地址:https://github.com/mgravell/protobuf-net

  开源项目地址如下:https://code.google.com/p/protobuf-net/,下载解压后的目录如下所示,每个文件夹的详细介绍都在最后一个txt文件里面了。

  protobuf-net

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

  }

  

}

  to be continue...

你可能感兴趣的:(protobuf)