手工使用Protobuf-net工具来序列化对象
2017-02-16 19:39
645 查看
如果用C#中BinaryFormatter的序列化方式,体积太大,因为序列化了好多类型信息。这个时候用protobuf是最好的选择。在Unity中,可以使用Protobuf-net。 下面是手工写proto的例子:
这个类,还可以用缺省写法:
另外,把byte[]数组显示出来的方式有:
复杂一些的例子:
更加复杂的例子:
using ProtoBuf;
using System.Collections.Generic;
using Game.Extensions;
using System.IO;
using System;
using System.Runtime.Serialization;
// 同步测试工具
public class SynDebug {
public static void protoTest() {
var st = new MyPlayer(1, 22, "harry");
st.readings.Add(new Book(1, "book1", 120));
st.readings.Add(new Book(2, "book2", 320));
st.readings.Add(new Book(3, "book3", 550));
st.ops.Add(new OP(1, 2, 3, 4, 5, 6, true, false, true));
st.ops.Add(new OP(6, 5, 4, 3, 2, 11, false, true, false));
var op = new OP(1, 2, 3, 4, 5, 6, true, false, true);
testValid(st);
}
public static void test01() {
DCardData cd = new DCardData(1, 2, true);
testValid(cd);
var player = createPlayer();
testValid(player);
var rd = createReplayData();
testValid(rd);
}
public static ReplayData createReplayData() {
ReplayData rd = new ReplayData(32111, createPlayer(1000), createPlayer(2000));
return rd;
}
public static DPlayerData createPlayer(int id = 1000) {
return new DPlayerData(new DCardData(id + 1, id + 1, true),
new DCardData[] {
new DCardData(id + 21, id + 21, true),
new DCardData(id + 22, id + 22, false),
new DCardData(id + 23, id + 23, true),
}, new List<OP> {
new OP(id + 31, 1, 1, 1, 331, 331, true, false, true),
new OP(id + 32, 2, 2, 2, 332, 332, false, true, false),
}, new MyGamePlayer(id + 111, "harry", 222, 333, 444));
}
//System.Convert.ToBase64String(buff2), ArrayConverter.toBinary(buff1)
private static void testValid<T>(T objO) {
using(MemoryStream mem = new MemoryStream()) {
//// 序列化到内存
Serializer.Serialize(mem, objO); //RuntimeTypeModel.Default.Serialize(mem, st);
// 模拟序列化到磁盘
byte[] buff1 = mem.ToArray();
string logStr = System.Convert.ToBase64String(buff1);
// 模拟从磁盘序反列化到内存
var buff2 = System.Convert.FromBase64String(logStr);
var mem2 = new MemoryStream(buff2);
// 从内存反序列化成对象
T objN = Serializer.Deserialize<T>(mem2); // RuntimeTypeModel.Default.Deserialize(mem2, null, typeof(Student)) as Student;
var bo = logStr;
var bn = System.Convert.ToBase64String(buff2);
var co = objO.ToString();
var cn = objN.ToString();
UnityEngine.Debug.LogFormat("isSame: {0}(b) {1}(c)\r\nbytes({2}) : {3}\r\n\r\nOLD:{4}\r\nNEW:{5}\r\n{6}",
bo.Equals(bn), co.Equals(cn),
buff1.Length, bo,
co,
cn,
ArrayConverter.toBinary(buff1)
);
}
}
}
[ProtoContract]
public class DPlayerData : BitField {
[ProtoMember(1)]
public DCardData hero;
[ProtoMember(2)]
public DCardData[] cards;
[ProtoMember(3)]
private List<byte[]> opDatas;
[ProtoMember(4)]
public int userid;
[ProtoMember(5)]
public int level;
[ProtoMember(6)]
public int pvpScore;
[ProtoMember(7)]
public int pvpLevel;
[ProtoMember(8)]
public string name;
public List<OP> operations;
public DPlayerData() { }
public DPlayerData(DCardData _hero, DCardData[] _cards, List<OP> _operstions, MyGamePlayer p) {
hero = _hero;
cards = _cards;
operations = _operstions;
userid = p.ID;
name = p.Name;
level = p.Level;
pvpScore = p.Score;
pvpLevel = p.PvpLevel;
}
//public void fillInfo(List<Common.Hero> hs, List<long> ops, Server.UserSummary us) {
// System.Array.ForEach(cards, c => { hs.Add(c.toHero()); });
// System.Array.ForEach(operations, op => { ops.Add(op); });
// us.userid = userid;
// us.name = name;
// us.level = level;
// us.pvpScore = pvpScore;
// us.pvpLevel = pvpLevel;
//}
[OnSerializing]
public void OnSerializing(StreamingContext context) {
opDatas = new List<byte[]>();
operations.ForEach(op => opDatas.Add(op.toArray()));
}
[OnDeserialized]
public void OnDeserialized(StreamingContext context) {
operations = new List<OP>();
opDatas.ForEach(opds => operations.Add(new OP(opds)));
}
public override string ToString() {
var cifs = string.Join(",", Array.ConvertAll(cards, c => c.ToString()));
var opinfs = string.Join(",", Array.ConvertAll(operations.ToArray(), op => op.ToString()));
return string.Format("hero: <{0}>, cards: <{1}>, ops: <{2}>, userid: {3}, level: {4}, pvpScore: {5}, pvpLevel: {6}, name: {7}",
hero.ToString(), cifs, opinfs, userid, level, pvpScore, pvpLevel, name);
}
}
public class MyGamePlayer {
public int ID;
public string Name;
public int Level;
public int Score;
public int PvpLevel;
public MyGamePlayer(int _Id, string _Name, int _Level, int _Score, int _PvpLevel) {
ID = _Id;
Name = _Name;
Level = _Level;
Score = _Score;
PvpLevel = _PvpLevel;
}
}
// 卡牌类型数据
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class DCardData {
public int id;
public int level;
public bool isHero;
public DCardData() { }
public DCardData(int _id, int _level, bool _isHero = false) {
id = _id;
level = _level;
isHero = _isHero;
}
public Common.Hero toHero() {
Common.Hero h = new Common.Hero();
h.tid = id;
h.level = level;
h.isHero = isHero ? 1 : 0;
return h;
}
public override string ToString() {
return string.Format("id: {0}, level: {1}, isHero: {2}", id, level, isHero);
}
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class ReplayData {
public int randomSeed;
public DateTime time;
public DPlayerData home;
public DPlayerData visit;
public ReplayData() { }
public ReplayData(int seed, DPlayerData _home, DPlayerData _visit) {
time = DateTime.UtcNow;
randomSeed = seed;
home = _home;
visit = _visit;
}
public override string ToString() {
return string.Format("seed: {0}, home: <{1}>, visit: <{2}>", randomSeed, home.ToString(), visit.ToString());
}
}
/**
* Encode MsgFrameOp to Int64, FrameNo : 0~15, Others: 16~31, DeployCard.X: 32~47, DeployCard.Y: 48~63
*
* 0 16 32 48 63
* ______________________________________________
* | FrameNo | Others | X | Y |
* ______________________________________________
*
* Other:
* 16 20 24 28 31
* _________________________________________________
* | Type | Deploy ID | Select ID | Face ID |
* _________________________________________________
*
* Type:
* 16 17 18 19
* __________________________________________________
* | DeployCard | SelectCard | MakeFace | not use |
* __________________________________________________
*
* */
public class OP : BitField {
[BitInfo(16)]
public int FrameNo;
[BitInfo(1)]
public bool isDeployCard;
[BitInfo(1)]
public bool isSelectCard;
[BitInfo(1)]
public bool isMakeFace;
[BitInfo(1)]
public bool NotUsed;
[BitInfo(4)]
public int DeployID;
[BitInfo(4)]
public int SelectID;
[BitInfo(4)]
public int FaceID;
[BitInfo(16)]
public int X;
[BitInfo(16)]
public int Y;
public OP(int FrameNo, int DeployID, int SelectID, int FaceID, int X, int Y, bool isDeployCard, bool isSelectCard, bool isMakeFace) {
this.FrameNo = FrameNo;
this.DeployID = DeployID;
this.SelectID = SelectID;
this.FaceID = FaceID;
this.X = X;
this.Y = Y;
this.isDeployCard = isDeployCard;
this.isSelectCard = isSelectCard;
this.isMakeFace = isMakeFace;
}
public OP(byte[] datas) {
parse(datas);
}
public new string ToString() {
return string.Format("<FrameNo: {0}, DeployID: {1}, SelectID: {2}, FaceID: {3}, X: {4}, Y: {5}, {6}, {7}, {8}>",
FrameNo, DeployID, SelectID, FaceID, X, Y, isDeployCard, isSelectCard, isMakeFace);
}
}
[ProtoContract(/*ImplicitFields = ImplicitFields.AllPublic*/)]
public class MyPlayer {
[ProtoMember(1)]
public int id;
[ProtoMember(2)]
public int age;
[ProtoMember(3)]
public string name;
[ProtoMember(4)]
public List<Book> readings = new List<Book>();
[ProtoMember(5)]
private List<byte[]> opData;
public List<OP> ops = new List<OP>();
public MyPlayer() { } // 缺省构造函数一定要有,否则不能调用Deserialize
public MyPlayer(int _id, int _age, string _name) {
id = _id;
age = _age;
name = _name;
}
[OnSerializing]
public void OnSerializing(StreamingContext context) {
opData = new List<byte[]>();
ops.ForEach(op => opData.Add(op.toArray()));
}
[OnDeserialized]
public void OnDeserialized(StreamingContext context) {
ops.Clear();
opData.ForEach(opds => ops.Add(new OP(opds)));
}
public override string ToString() {
return string.Format("id: {0}, age: {1}, name: {2}, readings: [{3}], Ops: [{4}]", id, age, name,
string.Join(", ", readings.ConvertAll(b => b.ToString()).ToArray()),
string.Join(", ", ops.ConvertAll(op => op.ToString()).ToArray()));
}
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Book {
public int bookNo;
public string name;
public int page;
public Book() {
}
public Book(int _no, string _name, int _page) {
bookNo = _no;
name = _name;
page = _page;
}
public new string ToString() {
return string.Format("<bookNo: {0}, name: {1}, page: {2}>", bookNo, name, page);
}
}
参考:
http://stackoverflow.com/questions/29155659/why-is-binaryformatter-trying-to-serialize-too-much-data
http://stackoverflow.com/questions/675349/deserialize-unknown-type-with-protobuf-net
http://stackoverflow.com/questions/12308196/protobuf-net-serialization-without-annotation
[ProtoContract] public class Student { [ProtoMember(1)] public int id; [ProtoMember(2)] public int age; [ProtoMember(3)] public string name; [ProtoMember(4)] public List<string> friends = new List<string>(); public Student() { } // 缺省构造函数一定要有,否则不能调用Deserialize public Student(int _id, int _age, string _name) { id = _id; age = _age; name = _name; } public new string ToString() { return string.Format("id: {0}, age: {1}, name: {2}, friends: {3}", id, age, name, string.Join(",", friends.ToArray())); } }
这个类,还可以用缺省写法:
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] public class Student { public int id; public int age; public string name; public List<string> friends = new List<string>(); public Student() { } // 缺省构造函数一定要有,否则不能调用Deserialize public Student(int _id, int _age, string _name) { id = _id; age = _age; name = _name; } public new string ToString() { return string.Format("id: {0}, age: {1}, name: {2}, friends: {3}", id, age, name, string.Join(",", friends.ToArray())); } }调用
[Test] public void protoTest() { using(MemoryStream mem = new MemoryStream()) { // 初始化 var st = new Student(1, 22, "harry"); st.friends = new List<string>() { "a", "b", "c", "d" }; // 序列化到内存 Serializer.Serialize(mem, st); //RuntimeTypeModel.Default.Serialize(mem, st); // 模拟序列化到磁盘 var buff = mem.ToArray(); string logStr = System.Convert.ToBase64String(buff); UnityEngine.Debug.Log(string.Format("size: {0}, {1}\r\n{2}", buff.Length, logStr, ArrayConverter.toBinary(buff))); // 模拟从磁盘序反列化到内存 var buff2 = System.Convert.FromBase64String(logStr); var mem2 = new MemoryStream(buff2); // 从内存反序列化成对象 Student st2 = Serializer.Deserialize<Student>(mem2); // RuntimeTypeModel.Default.Deserialize(mem2, null, typeof(Student)) as Student; UnityEngine.Debug.Log("old: " + st.ToString()); UnityEngine.Debug.Log("new: " + st2.ToString()); } }
另外,把byte[]数组显示出来的方式有:
byte[] buff = mem.ToArray(); // 1. 表示成二进制 ArrayConverter.toBinary(buff); // 2. 表示成六十四进制(方便保存到日志中): System.Convert.ToBase64String(buff); // 3. 反序列化 System.Convert.FromBase64String(logStr);
复杂一些的例子:
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] public class Student { public int id; public int age; public string name; public List<Book> readings = new List<Book>(); public Student() { } // 缺省构造函数一定要有,否则不能调用Deserialize public Student(int _id, int _age, string _name) { id = _id; age = _age; name = _name; } public new string ToString() { return string.Format("id: {0}, age: {1}, name: {2}, readings: [{3}]", id, age, name, string.Join(", ", readings.ConvertAll(b => b.ToString()).ToArray())); } } [ProtoContract(ImplicitFields = ImplicitFields.AllPublic)] public class Book { public int bookNo; public string name; public int page; public Book() { } public Book(int _no, string _name, int _page) { bookNo = _no; name = _name; page = _page; } public new string ToString() { return string.Format("<bookNo: {0}, name: {1}, page: {2}>", bookNo, name, page); } } // 调用 [Test] public void protoTest() { using(MemoryStream mem = new MemoryStream()) { // 初始化 var st = new Student(1, 22, "harry"); st.readings.Add(new Book(1, "book1", 120)); st.readings.Add(new Book(2, "book2", 320)); st.readings.Add(new Book(3, "book3", 550)); // 序列化到内存 Serializer.Serialize(mem, st); // 模拟序列化到磁盘 byte[] buff = mem.ToArray(); string logStr = System.Convert.ToBase64String(buff); UnityEngine.Debug.Log(string.Format("size: {0}, {1}\r\n{2}", buff.Length, logStr, ArrayConverter.toBinary(buff))); // 模拟从磁盘序反列化到内存 var buff2 = System.Convert.FromBase64String(logStr); var mem2 = new MemoryStream(buff2); // 从内存反序列化成对象 Student st2 = Serializer.Deserialize<Student>(mem2); UnityEngine.Debug.Log("old: " + st.ToString()); UnityEngine.Debug.Log("new: " + st2.ToString()); } }
更加复杂的例子:
using ProtoBuf;
using System.Collections.Generic;
using Game.Extensions;
using System.IO;
using System;
using System.Runtime.Serialization;
// 同步测试工具
public class SynDebug {
public static void protoTest() {
var st = new MyPlayer(1, 22, "harry");
st.readings.Add(new Book(1, "book1", 120));
st.readings.Add(new Book(2, "book2", 320));
st.readings.Add(new Book(3, "book3", 550));
st.ops.Add(new OP(1, 2, 3, 4, 5, 6, true, false, true));
st.ops.Add(new OP(6, 5, 4, 3, 2, 11, false, true, false));
var op = new OP(1, 2, 3, 4, 5, 6, true, false, true);
testValid(st);
}
public static void test01() {
DCardData cd = new DCardData(1, 2, true);
testValid(cd);
var player = createPlayer();
testValid(player);
var rd = createReplayData();
testValid(rd);
}
public static ReplayData createReplayData() {
ReplayData rd = new ReplayData(32111, createPlayer(1000), createPlayer(2000));
return rd;
}
public static DPlayerData createPlayer(int id = 1000) {
return new DPlayerData(new DCardData(id + 1, id + 1, true),
new DCardData[] {
new DCardData(id + 21, id + 21, true),
new DCardData(id + 22, id + 22, false),
new DCardData(id + 23, id + 23, true),
}, new List<OP> {
new OP(id + 31, 1, 1, 1, 331, 331, true, false, true),
new OP(id + 32, 2, 2, 2, 332, 332, false, true, false),
}, new MyGamePlayer(id + 111, "harry", 222, 333, 444));
}
//System.Convert.ToBase64String(buff2), ArrayConverter.toBinary(buff1)
private static void testValid<T>(T objO) {
using(MemoryStream mem = new MemoryStream()) {
//// 序列化到内存
Serializer.Serialize(mem, objO); //RuntimeTypeModel.Default.Serialize(mem, st);
// 模拟序列化到磁盘
byte[] buff1 = mem.ToArray();
string logStr = System.Convert.ToBase64String(buff1);
// 模拟从磁盘序反列化到内存
var buff2 = System.Convert.FromBase64String(logStr);
var mem2 = new MemoryStream(buff2);
// 从内存反序列化成对象
T objN = Serializer.Deserialize<T>(mem2); // RuntimeTypeModel.Default.Deserialize(mem2, null, typeof(Student)) as Student;
var bo = logStr;
var bn = System.Convert.ToBase64String(buff2);
var co = objO.ToString();
var cn = objN.ToString();
UnityEngine.Debug.LogFormat("isSame: {0}(b) {1}(c)\r\nbytes({2}) : {3}\r\n\r\nOLD:{4}\r\nNEW:{5}\r\n{6}",
bo.Equals(bn), co.Equals(cn),
buff1.Length, bo,
co,
cn,
ArrayConverter.toBinary(buff1)
);
}
}
}
[ProtoContract]
public class DPlayerData : BitField {
[ProtoMember(1)]
public DCardData hero;
[ProtoMember(2)]
public DCardData[] cards;
[ProtoMember(3)]
private List<byte[]> opDatas;
[ProtoMember(4)]
public int userid;
[ProtoMember(5)]
public int level;
[ProtoMember(6)]
public int pvpScore;
[ProtoMember(7)]
public int pvpLevel;
[ProtoMember(8)]
public string name;
public List<OP> operations;
public DPlayerData() { }
public DPlayerData(DCardData _hero, DCardData[] _cards, List<OP> _operstions, MyGamePlayer p) {
hero = _hero;
cards = _cards;
operations = _operstions;
userid = p.ID;
name = p.Name;
level = p.Level;
pvpScore = p.Score;
pvpLevel = p.PvpLevel;
}
//public void fillInfo(List<Common.Hero> hs, List<long> ops, Server.UserSummary us) {
// System.Array.ForEach(cards, c => { hs.Add(c.toHero()); });
// System.Array.ForEach(operations, op => { ops.Add(op); });
// us.userid = userid;
// us.name = name;
// us.level = level;
// us.pvpScore = pvpScore;
// us.pvpLevel = pvpLevel;
//}
[OnSerializing]
public void OnSerializing(StreamingContext context) {
opDatas = new List<byte[]>();
operations.ForEach(op => opDatas.Add(op.toArray()));
}
[OnDeserialized]
public void OnDeserialized(StreamingContext context) {
operations = new List<OP>();
opDatas.ForEach(opds => operations.Add(new OP(opds)));
}
public override string ToString() {
var cifs = string.Join(",", Array.ConvertAll(cards, c => c.ToString()));
var opinfs = string.Join(",", Array.ConvertAll(operations.ToArray(), op => op.ToString()));
return string.Format("hero: <{0}>, cards: <{1}>, ops: <{2}>, userid: {3}, level: {4}, pvpScore: {5}, pvpLevel: {6}, name: {7}",
hero.ToString(), cifs, opinfs, userid, level, pvpScore, pvpLevel, name);
}
}
public class MyGamePlayer {
public int ID;
public string Name;
public int Level;
public int Score;
public int PvpLevel;
public MyGamePlayer(int _Id, string _Name, int _Level, int _Score, int _PvpLevel) {
ID = _Id;
Name = _Name;
Level = _Level;
Score = _Score;
PvpLevel = _PvpLevel;
}
}
// 卡牌类型数据
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class DCardData {
public int id;
public int level;
public bool isHero;
public DCardData() { }
public DCardData(int _id, int _level, bool _isHero = false) {
id = _id;
level = _level;
isHero = _isHero;
}
public Common.Hero toHero() {
Common.Hero h = new Common.Hero();
h.tid = id;
h.level = level;
h.isHero = isHero ? 1 : 0;
return h;
}
public override string ToString() {
return string.Format("id: {0}, level: {1}, isHero: {2}", id, level, isHero);
}
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class ReplayData {
public int randomSeed;
public DateTime time;
public DPlayerData home;
public DPlayerData visit;
public ReplayData() { }
public ReplayData(int seed, DPlayerData _home, DPlayerData _visit) {
time = DateTime.UtcNow;
randomSeed = seed;
home = _home;
visit = _visit;
}
public override string ToString() {
return string.Format("seed: {0}, home: <{1}>, visit: <{2}>", randomSeed, home.ToString(), visit.ToString());
}
}
/**
* Encode MsgFrameOp to Int64, FrameNo : 0~15, Others: 16~31, DeployCard.X: 32~47, DeployCard.Y: 48~63
*
* 0 16 32 48 63
* ______________________________________________
* | FrameNo | Others | X | Y |
* ______________________________________________
*
* Other:
* 16 20 24 28 31
* _________________________________________________
* | Type | Deploy ID | Select ID | Face ID |
* _________________________________________________
*
* Type:
* 16 17 18 19
* __________________________________________________
* | DeployCard | SelectCard | MakeFace | not use |
* __________________________________________________
*
* */
public class OP : BitField {
[BitInfo(16)]
public int FrameNo;
[BitInfo(1)]
public bool isDeployCard;
[BitInfo(1)]
public bool isSelectCard;
[BitInfo(1)]
public bool isMakeFace;
[BitInfo(1)]
public bool NotUsed;
[BitInfo(4)]
public int DeployID;
[BitInfo(4)]
public int SelectID;
[BitInfo(4)]
public int FaceID;
[BitInfo(16)]
public int X;
[BitInfo(16)]
public int Y;
public OP(int FrameNo, int DeployID, int SelectID, int FaceID, int X, int Y, bool isDeployCard, bool isSelectCard, bool isMakeFace) {
this.FrameNo = FrameNo;
this.DeployID = DeployID;
this.SelectID = SelectID;
this.FaceID = FaceID;
this.X = X;
this.Y = Y;
this.isDeployCard = isDeployCard;
this.isSelectCard = isSelectCard;
this.isMakeFace = isMakeFace;
}
public OP(byte[] datas) {
parse(datas);
}
public new string ToString() {
return string.Format("<FrameNo: {0}, DeployID: {1}, SelectID: {2}, FaceID: {3}, X: {4}, Y: {5}, {6}, {7}, {8}>",
FrameNo, DeployID, SelectID, FaceID, X, Y, isDeployCard, isSelectCard, isMakeFace);
}
}
[ProtoContract(/*ImplicitFields = ImplicitFields.AllPublic*/)]
public class MyPlayer {
[ProtoMember(1)]
public int id;
[ProtoMember(2)]
public int age;
[ProtoMember(3)]
public string name;
[ProtoMember(4)]
public List<Book> readings = new List<Book>();
[ProtoMember(5)]
private List<byte[]> opData;
public List<OP> ops = new List<OP>();
public MyPlayer() { } // 缺省构造函数一定要有,否则不能调用Deserialize
public MyPlayer(int _id, int _age, string _name) {
id = _id;
age = _age;
name = _name;
}
[OnSerializing]
public void OnSerializing(StreamingContext context) {
opData = new List<byte[]>();
ops.ForEach(op => opData.Add(op.toArray()));
}
[OnDeserialized]
public void OnDeserialized(StreamingContext context) {
ops.Clear();
opData.ForEach(opds => ops.Add(new OP(opds)));
}
public override string ToString() {
return string.Format("id: {0}, age: {1}, name: {2}, readings: [{3}], Ops: [{4}]", id, age, name,
string.Join(", ", readings.ConvertAll(b => b.ToString()).ToArray()),
string.Join(", ", ops.ConvertAll(op => op.ToString()).ToArray()));
}
}
[ProtoContract(ImplicitFields = ImplicitFields.AllPublic)]
public class Book {
public int bookNo;
public string name;
public int page;
public Book() {
}
public Book(int _no, string _name, int _page) {
bookNo = _no;
name = _name;
page = _page;
}
public new string ToString() {
return string.Format("<bookNo: {0}, name: {1}, page: {2}>", bookNo, name, page);
}
}
参考:
http://stackoverflow.com/questions/29155659/why-is-binaryformatter-trying-to-serialize-too-much-data
http://stackoverflow.com/questions/675349/deserialize-unknown-type-with-protobuf-net
http://stackoverflow.com/questions/12308196/protobuf-net-serialization-without-annotation
相关文章推荐
- C# 使用 protobuf 进行对象序列化与反序列化
- C#使用Protocol Buffer(ProtoBuf)进行对象的序列化与反序列化
- Simple-Spring-Memcached使用Protobuf序列化Java对象
- Beetle使用Protobuf.net进行对象序列化传输
- java中使用protobuf序列化(反序列化)
- 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)
- 【protobuf 001】 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)
- Android下使用Protobuf进行序列化
- java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子
- c++ java中关于protobuf反序列化对象实体和实体处理(函数)关系 (一)
- 最常用的两种C++序列化方案的使用心得(protobuf和boost serialization)
- java序列化/反序列化之xstream、protobuf、protostuff 的比较与使用例子
- java序列化/反序列化之xstream、protobuf、protostuff 的比较与使用例子
- c#序列化与反序列化数据加密, 使用protobuf-net实现
- 最经常使用的两种C++序列化方案的使用心得(protobuf和boost serialization)
- java序列化/反序列化之xml、protobuf、protostuff 的比较与使用例子
- Java数据通讯中使用Googgle Protobuf 序列化与反序列化
- unity3d中使用proto对象进行序列化和反序列化
- 关于unity中 使用Protorbuf-net 序列化对象(iphone)
- Netty(五)序列化protobuf在netty中的使用