1. 程式人生 > 其它 >.Net 解析和序列化protocol buffers

.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 擴充套件包解析,較方便快捷。

這裡主要介紹第二種方式。

我們首先要確定protobuf檔案:

syntax = "proto3";
package Test;
message ProtoBufExample
{
    uint32 item1 = 1; // 欄位
    uint32 item2 = 2; // 欄位2
}

這裡是一個簡單的protobuf檔案:第一行syntax用來指定語法,比如這裡使用的就是proto3,也有使用proto2的,語法有所區別,proto3去掉了required等關鍵字。第二行的package是指包名,類似於C# namespace.

然後我們需要定義與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);

這樣就完成呼叫或者解析了,非常方便和快捷。

如有錯誤,歡迎指正,互相學習。謝謝!