返回顶部
首页 > 资讯 > 后端开发 > GO >Google.Protobuf工具在C#中的使用方法
  • 115
分享到

Google.Protobuf工具在C#中的使用方法

2024-04-02 19:04:59 115人浏览 独家记忆
摘要

protobuf是一个语言无关、平台无关的序列化协议,由谷歌开源提供。再加上其高性能、存储占用更小等特点,在云原生的应用中越来越广泛。 在C#中主要有两种方法来使用protobuf协

protobuf是一个语言无关、平台无关的序列化协议,由谷歌开源提供。再加上其高性能、存储占用更小等特点,在云原生的应用中越来越广泛。

C#中主要有两种方法来使用protobuf协议,nuget包分别为Google.Protobufprotobuf-net,其中Google.Protobuf由谷歌官方提供。本文简要记录和展示Google.Protobuf的使用方法和特点。

项目资料及文档

  • 项目官网:https://developers.google.cn/protocol-buffers?hl=zh-cn
  • GitHub主页:Https://github.com/protocolbuffers/protobuf/
  • 官方文档:https://developers.google.cn/protocol-buffers/docs/overview?hl=zh-cn
  • 该nuget包支持.netFramework 4.5、.NETStandard1.1、.net5等

准备工作

需要用到的nuget有如下两个:Google.ProtobufGoogle.Protobuf.Tools,其中Google.Protobuf是主类库,运行时要用到。Google.Protobuf.Tools提供了命令行工具,用于根据.proto文件转为目标语言的类型,仅开发时使用,运行时不需要。

本次Demo使用的.proto文件内容如下:


syntax = "proto3";
option cc_enable_arenas = true;

package Tccc.Demo.Protobuf;

message ErrorLog {
    string LogID = 1;
    string Context = 2;
    string Stack = 3;
}

首先需要根据.proto文件生成目标类型,操作如下:


./google.protobuf.tools\3.19.1\tools\windows_x64\protoc.exe --csharp_out=./generatedCode ./proto/ErrorLog.proto

其中--csharp_out选项是生成C#语言的目标类型,运行protoc.exe -h 查看帮助信息,可以看到还支持一下几种选项:


--proto_path=PATH
--cpp_out=OUT_DIR Generate c++ header and source.
--csharp_out=OUT_DIR Generate C# source file.
--java_out=OUT_DIR Generate Java source file.
--js_out=OUT_DIR Generate javascript source.
--Kotlin_out=OUT_DIR Generate Kotlin file.
--objc_out=OUT_DIR Generate Objective-C header and source.
--PHP_out=OUT_DIR Generate php source file.
--python_out=OUT_DIR Generate Python source file.
--ruby_out=OUT_DIR Generate Ruby source file.

运行上述命令,会根据指定的ErrorLog.proto文件生成ErrorLog.cs文件,文件中就是C#类型ErrorLog。生成的代码中会给此类型增加方法void WriteTo(CodedOutputStream output)和只读属性Parser,接下来进行序列化和反序列化的关键。

生成的ErrorLog类的完整代码:


// <auto-generated>
//     Generated by the protocol buffer compiler.  DO NOT EDIT!
//     source: ProtoFiles/ErrorLog.proto
// </auto-generated>
#pragma warning disable 1591, 0612, 3021
#region Designer generated code

using pb = global::Google.Protobuf;
using pbc = global::Google.Protobuf.Collections;
using pbr = global::Google.Protobuf.Reflection;
using scg = global::System.Collections.Generic;
namespace Tccc.Demo.Protobuf {

  /// <summary>Holder for reflection infORMation generated from ProtoFiles/ErrorLog.proto</summary>
  public static partial class ErrorLogReflection {

    #region Descriptor
    /// <summary>File descriptor for ProtoFiles/ErrorLog.proto</summary>
    public static pbr::FileDescriptor Descriptor {
      get { return descriptor; }
    }
    private static pbr::FileDescriptor descriptor;

    static ErrorLogReflection() {
      byte[] descriptorData = global::System.Convert.FromBase64String(
          string.Concat(
            "ChlQcm90b0ZpbGVzL0Vycm9yTG9nLnByb3RvEhJUY2NjLkRlbW8uUHJvdG9i",
            "dWYiOQoIRXJyb3JMb2cSDQoFTG9nSUQYASABKAkSDwoHQ29udGV4dBGCIAEo",
            "CRINCgVTdGFjaxgDIAEoCUID+AEBYgZwcm90bzM="));
      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
          new pbr::FileDescriptor[] { },
          new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
            new pbr::GeneratedClrTypeInfo(typeof(global::Tccc.Demo.Protobuf.ErrorLog), global::Tccc.Demo.Protobuf.ErrorLog.Parser, new[]{ "LogID", "Context", "Stack" }, null, null, null, null)
          }));
    }
    #endregion

  }
  #region Messages
  public sealed partial class ErrorLog : pb::IMessage<ErrorLog>
  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
      , pb::IBufferMessage
  #endif
  {
    private static readonly pb::MessageParser<ErrorLog> _parser = new pb::MessageParser<ErrorLog>(() => new ErrorLog());
    private pb::UnknownFieldSet _unknownFields;
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public static pb::MessageParser<ErrorLog> Parser { get { return _parser; } }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public static pbr::MessageDescriptor Descriptor {
      get { return global::Tccc.Demo.Protobuf.ErrorLogReflection.Descriptor.MessageTypes[0]; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    pbr::MessageDescriptor pb::IMessage.Descriptor {
      get { return Descriptor; }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public ErrorLog() {
      OnConstruction();
    }

    partial void OnConstruction();

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public ErrorLog(ErrorLog other) : this() {
      logID_ = other.logID_;
      context_ = other.context_;
      stack_ = other.stack_;
      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public ErrorLog Clone() {
      return new ErrorLog(this);
    }

    /// <summary>Field number for the "LogID" field.</summary>
    public const int LogIDFieldNumber = 1;
    private string logID_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public string LogID {
      get { return logID_; }
      set {
        logID_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "Context" field.</summary>
    public const int ContextFieldNumber = 2;
    private string context_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public string Context {
      get { return context_; }
      set {
        context_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    /// <summary>Field number for the "Stack" field.</summary>
    public const int StackFieldNumber = 3;
    private string stack_ = "";
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public string Stack {
      get { return stack_; }
      set {
        stack_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
      }
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public override bool Equals(object other) {
      return Equals(other as ErrorLog);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public bool Equals(ErrorLog other) {
      if (ReferenceEquals(other, null)) {
        return false;
      }
      if (ReferenceEquals(other, this)) {
        return true;
      }
      if (LogID != other.LogID) return false;
      if (Context != other.Context) return false;
      if (Stack != other.Stack) return false;
      return Equals(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public override int GetHashCode() {
      int hash = 1;
      if (LogID.Length != 0) hash ^= LogID.GetHashCode();
      if (Context.Length != 0) hash ^= Context.GetHashCode();
      if (Stack.Length != 0) hash ^= Stack.GetHashCode();
      if (_unknownFields != null) {
        hash ^= _unknownFields.GetHashCode();
      }
      return hash;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public override string ToString() {
      return pb::JSONFormatter.ToDiagnosticString(this);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void WriteTo(pb::CodedOutputStream output) {
    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
      output.WriteRawMessage(this);
    #else
      if (LogID.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(LogID);
      }
      if (Context.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Context);
      }
      if (Stack.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(Stack);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(output);
      }
    #endif
    }

    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
      if (LogID.Length != 0) {
        output.WriteRawTag(10);
        output.WriteString(LogID);
      }
      if (Context.Length != 0) {
        output.WriteRawTag(18);
        output.WriteString(Context);
      }
      if (Stack.Length != 0) {
        output.WriteRawTag(26);
        output.WriteString(Stack);
      }
      if (_unknownFields != null) {
        _unknownFields.WriteTo(ref output);
      }
    }
    #endif

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public int CalculateSize() {
      int size = 0;
      if (LogID.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(LogID);
      }
      if (Context.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Context);
      }
      if (Stack.Length != 0) {
        size += 1 + pb::CodedOutputStream.ComputeStringSize(Stack);
      }
      if (_unknownFields != null) {
        size += _unknownFields.CalculateSize();
      }
      return size;
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void MergeFrom(ErrorLog other) {
      if (other == null) {
        return;
      }
      if (other.LogID.Length != 0) {
        LogID = other.LogID;
      }
      if (other.Context.Length != 0) {
        Context = other.Context;
      }
      if (other.Stack.Length != 0) {
        Stack = other.Stack;
      }
      _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
    }

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    public void MergeFrom(pb::CodedInputStream input) {
    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
      input.ReadRawMessage(this);
    #else
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
            break;
          case 10: {
            LogID = input.ReadString();
            break;
          }
          case 18: {
            Context = input.ReadString();
            break;
          }
          case 26: {
            Stack = input.ReadString();
            break;
          }
        }
      }
    #endif
    }

    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
    void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
      uint tag;
      while ((tag = input.ReadTag()) != 0) {
        switch(tag) {
          default:
            _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
            break;
          case 10: {
            LogID = input.ReadString();
            break;
          }
          case 18: {
            Context = input.ReadString();
            break;
          }
          case 26: {
            Stack = input.ReadString();
            break;
          }
        }
      }
    }
    #endif

  }

  #endregion

}

#endregion Designer generated code

序列化操作


public static byte[] Serialize(ErrorLog log)
        {
            using (MemoryStream output = new MemoryStream())
            {
                log.WriteTo(output);
                return output.ToArray();
            }
        }

反序列化操作


ErrorLog desErrorLog= ErrorLog.Parser.ParseFrom(data);

使用特点和理解

  • protoc.exe是支持生成多语言类型,这对于跨语言的混合编程比较方便。
  • 根据上述使用步骤可以看到,必须先使用工具protoc生成目标类型,才能调用序列化和反序列化方法,这有些不符合.net平台的编码习惯。
  • 一堆自动生成的C#类在可维护性方面欠佳,当需要调整属性字段时,还要通过工具重新生成,较为麻烦。

到此这篇关于Google.Protobuf工具在C#中的使用方法就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

您可能感兴趣的文档:

--结束END--

本文标题: Google.Protobuf工具在C#中的使用方法

本文链接: https://lsjlt.com/news/158287.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Google.Protobuf工具在C#中的使用方法
    protobuf是一个语言无关、平台无关的序列化协议,由谷歌开源提供。再加上其高性能、存储占用更小等特点,在云原生的应用中越来越广泛。 在C#中主要有两种方法来使用protobuf协...
    99+
    2024-04-02
  • Protobuf工具在C#中的使用方法是什么
    这篇文章主要讲解了“Protobuf工具在C#中的使用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Protobuf工具在C#中的使用方法是什么”吧!protobuf是一个语言无关...
    99+
    2023-06-21
  • 在Linux下HTTPie工具的使用方法
    本篇内容主要讲解“在Linux下HTTPie工具的使用方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“在Linux下HTTPie工具的使用方法”吧!如果你经常需要通过终端以非交互模式访问网络服...
    99+
    2023-06-13
  • Java中StringJoiner工具的使用方法
    这篇文章将为大家详细讲解有关Java中StringJoiner工具的使用方法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。背景在平时的业务开发中,我们可能会遇到字符串列表根据分隔符进行拼接的需求。比如:输...
    99+
    2023-06-15
  • charles工具的使用方法
    本篇内容介绍了“charles工具的使用方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!1. Charles 简介好多人把它叫做抓包工具,...
    99+
    2023-06-02
  • 如何使用C++中的C++Test工具
    如何使用C++中的C++Test工具,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。C++Test工具允许你定制白盒测试用例的生成,和在什么层次上(项目、文件、类或方法)执行测试...
    99+
    2023-06-17
  • dbgen工具使用方法
    本文将介绍dbgen多线程的使用方法: dbgen是用来生成TPCH 所需要的数据来使用的   TPCH :针对于数据库查询性能的压测方法   #:首先使用dbgen来生成数据 这里数据量业界有一个统称叫做SF  1SF == 1G [[e...
    99+
    2016-10-28
    dbgen工具使用方法 数据库入门 数据库基础教程 数据库 mysql
  • AD Sync工具使用方法
    今天小编就为大家带来一篇有关AD Sync工具使用方法的文章。小编觉得挺实用的,为此分享给大家做个参考。一起跟随小编过来看看吧。AAD Sync是我们的新目录同步工具,可简化将Azure AD连接到Wind...
    99+
    2024-04-02
  • 使用mysql自带工具的方法
    下文给大家带来关于使用mysql自带工具的方法,感兴趣的话就一起来看看这篇文章吧,相信看完使用mysql自带工具的方法对大家多少有点帮助吧。1)mysql命令:mysql命令事是使用最多的命令工具了,为用户...
    99+
    2024-04-02
  • 正确使用dotnet-*工具的方法
    目录安装验证dotnet-dumpcreatedump分析coredump文件相关资料:安装 因为我们现在都是容器化时代了,所以我们可以把这类工具全部制作成基础镜像 ...
    99+
    2024-04-02
  • 正确使用dotnet工具的方法
    正确使用dotnet工具的方法有以下几步:1. 安装dotnet SDK:首先需要在计算机上安装dotnet SDK,可以从dotn...
    99+
    2023-08-16
    dotnet
  • win10升级工具的使用方法
    想要升级win10系统,但是又没有找到合适的win10升级工具?今天小编就给大家介绍一款好用的win10升级工具——win10升级助手。今天小编将为大家介绍win10升级工具的使用教程,请大家一同观看。1、首先我们要在微软官方网站中下载微软...
    99+
    2023-07-10
  • cypress中丰富的调试工具使用方法
    目录cypress调试工具一、 Time travel二、 快照三、errors信息四、页面事件五、控制台的输出六、调试专用命令cypress调试工具 Cypress附带了一系列调试...
    99+
    2024-04-02
  • Node版本管理工具nvm在windows的使用方法
    这篇文章主要讲解了“Node版本管理工具nvm在windows的使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Node版本管理工具nvm在windo...
    99+
    2024-04-02
  • oracle 11g adrci 工具使用方法
    oracle 11g adrci  是11g 以后才能的新功能 [oracle@rac1 ~]$ adrci ADRCI: Release 11.2.0.4.0 - Production...
    99+
    2024-04-02
  • win7activation激活工具使用方法
    所有的windows系统,包括win7,都需要激活方可享用全部功能。那么如何激活win7呢?常用的方法就是借助win7激活码或者win7激活工具,而比较好用的就是win7activation激活工具了。小编接下来会向大家介绍一下win7ac...
    99+
    2023-07-17
  • Oracle 测试工具 Swingbench 的使用方法
    1、安装 JDK 1.82、安装 Wingbench,下载 解压即可3、初始化模式 SOE 的数据,双击 D:\swingbench\winbin\oewizard 24、执行测试,双击D:\swingbe...
    99+
    2024-04-02
  • JS/CSS压缩工具的使用方法
    这篇文章主要讲解了“JS/CSS压缩工具的使用方法”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“JS/CSS压缩工具的使用方法”吧!网页访问速度慢如何提高呢...
    99+
    2024-04-02
  • llinux fdisk分区工具的使用方法
    这篇文章主要介绍“llinux fdisk分区工具的使用方法”,在日常操作中,相信很多人在llinux fdisk分区工具的使用方法问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”llinux fdisk分区工...
    99+
    2023-06-10
  • mongodb工具使用的方法是什么
    MongoDB是一个非关系型数据库,它提供了一些工具来与数据库进行交互和管理。以下是一些常用的MongoDB工具的使用方法:1. M...
    99+
    2023-09-12
    mongodb
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作