• .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

    如有错误,欢迎指正,互相学习。谢谢!
  • 相关阅读:
    BTree B+Tree
    SpringMvc框架 解决在RESTFUL接口后加任意 “.xxx” 绕过权限的问题
    多线程基础知识---sleep和wait区别
    多线程基础知识---join方法
    Maven跳过单元测试的两种方式
    maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令
    Maven项目版本继承 – 我必须指定父版本?
    SpringMVC 零配置 无web.xml
    利用ApplicationContextAware装配Bean
    Spring Boot 读取 resource 下文件
  • 原文地址:https://www.cnblogs.com/Ivan-Wu/p/15038586.html
Copyright © 2020-2023  润新知