protocol buffers被越来越多开发者使用,比如在grpc中用到,或者使用protobuf与游戏进行通信,也有游戏使用它来保存游戏数据的。
为什么我们要使用protobuf?
protocol buffers 是一种灵活,高效,自动化机制的结构数据序列化方法-可类比 XML,但是比 XML 更小、更快、更为简单。
当然解析protobuf有几种方式:
1、使用官方软件工具包生成C# 文件,按照官方教程就可以直接解析了。官方protobuf C#教程:https://developers.google.com/protocol-buffers/docs/csharptutorial
2、使用ServiceStack.ProtoBuf 扩展包解析,较方便快捷。
第一种方式:
通过nuget包下载 Google.Protobuf.Tools这个包,里面有proto.exe 工具,按照官方文档命令就可以输出cs文件:
protoc.exe --proto_path=. --csharp_out=. main.proto // 输出到当前目录
这里的main.proto就是需要转换的proto文件
第二种方式:
我们首先要确定protobuf文件:
syntax = "proto3"; package Test; message ProtoBufExample { uint32 item1 = 1; // 字段 uint32 item2 = 2; // 字段2 }
这里是一个简单的protobuf文件:第一行syntax用来指定语法,比如这里使用的就是proto3,也有使用proto2的,语法有所区别,proto3去掉了required等关键字。第二行的package是指包名,类似于C# namespace.
proto2官方说明: https://developers.google.com/protocol-buffers/docs/proto
proto3官方说明:https://developers.google.com/protocol-buffers/docs/proto3
然后我们需要定义与proto文件相同的类:
[ProtoContract] public class ProtoBufExample { /// <summary> /// 字段1 /// </summary> [ProtoMember(1)] public uint item1 { get; set; } /// <summary> /// 字段2 /// </summary> [ProtoMember(2)] public uint item2 { get; set; } }
类需要加上 [ProtoContract]特性,属性需要和proto文件中的字段对应上。
接下来就是解析和序列化了,定义一个静态类:
public static class ProtoBufExtensions { /// <summary> /// object To bytes /// </summary> /// <typeparam name="T"></typeparam> /// <param name="instance"></param> /// <returns></returns> public static byte[] ObjectToBytes<T>(T instance) { try { byte[] array; if (instance == null) { array = new byte[0]; } else { var memoryStream = new MemoryStream(); Serializer.Serialize(memoryStream, instance); array = new byte[memoryStream.Length]; memoryStream.Position = 0L; memoryStream.Read(array, 0, array.Length); memoryStream.Dispose(); } return array; } catch (Exception ex) { return new byte[0]; } } /// <summary> /// byte To Object /// </summary> /// <typeparam name="T"></typeparam> /// <param name="bytesData"></param> /// <returns></returns> public static T BytesToObject<T>(byte[] bytesData) { if (bytesData.Length == 0) return default; try { var memoryStream = new MemoryStream(); memoryStream.Write(bytesData, 0, bytesData.Length); memoryStream.Position = 0L; var result = Serializer.Deserialize<T>(memoryStream); memoryStream.Dispose(); return result; } catch (Exception ex) { return default; } } }
然后就是调用:
// 序列化 byte[] result = ProtoBufExtensions.ObjectToBytes<ProtoBufExample>(protoBufExample); //解析 var result = ProtoBufExtensions.BytesToObject<ProtoBufExample>(byteAarry);
这样就完成调用或者解析了,非常方便和快捷。
附上链接:
ServiceStack.ProtoBuf github地址 :https://github.com/ServiceStack/ServiceStack
官方开发者文档:https://developers.google.com/protocol-buffers/docs/overview