protobuf-net

糜昌胤
2023-12-01

本文转自:http://www.cnblogs.com/xuf22/articles/3504399.html

http://blog.csdn.net/lyh916/article/details/50992329,请点击链接查看原文,尊重楼主版权。

protobuf-net官方下载地址:https://code.google.com/archive/p/protobuf-net/downloads?page=1
为了方便,这里直接给出protobuf-net.dll的下载地址:http://pan.baidu.com/s/1hs53Dty


什么是ProtoBuf-net


Protobuf是google开源的一个项目,用户数据序列化反序列化,google声称google的数据通信都是用该序列化方法。它比xml格式要少的多,甚至比二进制数据格式也小的多。

Protobuf格式协议和xml一样具有平台独立性,可以在不同平台间通信,通信所需资源很少,并可以扩展,可以旧的协议上添加新数据

Protobuf是在java和c++运行的,Protobuf-net当然就是Protobuf在.net环境下的移植。


测试:
1.把protobuf-net.dll放入unity中
2.类前加上ProtoContract,成员加上ProtoMember即可,其中ProtoMember需要一个大于0的int类型的值,原则上这个int类型没有大小限制,但建议从1开始,这是一个良好的习惯,另外这个参数必需是这个类成员的唯一标识,不可重复。

using ProtoBuf;  
  
[ProtoContract]  
public class User  
{  
    [ProtoMember(1)]  
    public int UserID { get; set; }  
  
    [ProtoMember(2)]  
    public string UserName { get; set; }  
}  

using UnityEngine;  
using System.Collections.Generic;  
using System.IO;  
using UnityEditor;  
using ProtoBuf;  
  
public class TestProtoBuf {  
  
    [MenuItem("Test/TestProtoBuf")]  
    static void Execute ()  
    {  
        List<User> list = new List<User>();  
        for (int i = 0; i < 100; i++)  
        {  
            list.Add(new User() { UserID = i, UserName = "u" + i.ToString() });  
        }  
  
        //序列化  
        string path = Application.dataPath + "/ProtoBuf.txt";  
        using (Stream file = File.Create(path))  
        {  
            Serializer.Serialize<List<User>>(file, list);  
            file.Close();  
        }  
  
        //反序列化  
        List<User> list2 = new List<User>();  
        using (Stream file = File.OpenRead(path))  
        {  
            list2 = Serializer.Deserialize<List<User>>(file);  
            file.Close();  
        }  
        foreach (User u in list2)  
        {  
            Debug.Log(string.Format("UserID={0}, UserName={1}", u.UserID, u.UserName));  
        }  
  
        AssetDatabase.Refresh();  
    }  
  
}  

因为protobuf是二进制报文,没有xml格式这样的可读性,要想看懂报文内容只能用ProtoBuf反序列化了。


.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是可以重复的字段(即表示数组或列表),同时枚举字段都必须给出默认值。


其中ProtoGen是用来根据.proto文件生成对应的.cs文件,命令行如下:
protogen -i:test.proto -0:test.cs -ns:MyProtoBuf


-i指定了输入,-o指定了输出,-ns指定了生成代码的namespace,上面的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); }  
  }  
    
}  

更多关于.proto文件的语法,可以看: http://www.cnblogs.com/dkblog/archive/2012/03/27/2419010.html


 类似资料: