[C#基础]网络编程(三):protobuf-net

本文介绍如何使用protobuf-net库在Unity中进行序列化与反序列化操作,包括dll引入、成员注解及简单实例演示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

相关链接:

http://www.cnblogs.com/xuf22/articles/3504399.html

http://blog.youkuaiyun.com/ddxkjddx/article/details/7239798

http://www.cnblogs.com/sifenkesi/p/4045392.html

protobuf-net官方下载地址:https://code.google.com/archive/p/protobuf-net/downloads?page=1

为了方便,这里直接给出protobuf-net.dll的下载地址:http://pan.baidu.com/s/1hs53Dty


测试:

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值