8 24 81

.Net 解析和序列化Protocol Buffers

      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

posted @ 2021-07-21 17:21  Ivan_Ivan  阅读(207)  评论(0编辑  收藏  举报