我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Protobuf工具在C#中的使用方法是什么

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Protobuf工具在C#中的使用方法是什么

这篇文章主要讲解了“Protobuf工具在C#中的使用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Protobuf工具在C#中的使用方法是什么”吧!

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

在C#中主要有两种方法来使用protobuf协议,nuget包分别为Google.Protobufprotobuf-net,其中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 codeusing 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#类在可维护性方面欠佳,当需要调整属性字段时,还要通过工具重新生成,较为麻烦。

感谢各位的阅读,以上就是“Protobuf工具在C#中的使用方法是什么”的内容了,经过本文的学习后,相信大家对Protobuf工具在C#中的使用方法是什么这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是编程网,小编将为大家推送更多相关知识点的文章,欢迎关注!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Protobuf工具在C#中的使用方法是什么

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Protobuf工具在C#中的使用方法是什么

这篇文章主要讲解了“Protobuf工具在C#中的使用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Protobuf工具在C#中的使用方法是什么”吧!protobuf是一个语言无关
2023-06-21

c++中protobuf的用法是什么

在C++中使用protobuf,首先需要定义一个.proto文件来描述消息的结构,然后使用protobuf的编译器生成对应的C++代码。接着可以在C++程序中使用生成的代码来序列化和反序列化消息。以下是一个简单的使用protobuf的示例
c++中protobuf的用法是什么
2024-03-05

c++中protobuf的作用是什么

在C++中,Protobuf(Protocol Buffers)的作用是用于序列化结构化数据,以便在不同系统之间进行数据交换或持久化存储。它提供了一个简单而高效的方法来定义数据结构,并生成对应的代码来进行数据的序列化和反序列化操作。使用Pr
c++中protobuf的作用是什么
2024-03-05

mongodb工具使用的方法是什么

MongoDB是一个非关系型数据库,它提供了一些工具来与数据库进行交互和管理。以下是一些常用的MongoDB工具的使用方法:1. MongoDB Shell:MongoDB提供了一个交互式的JavaScript shell,可以通过命令行与
2023-09-12

Linux命令工具的使用方法是什么

这篇文章给大家介绍Linux命令工具的使用方法是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Linux 上有太多的命令了,如果背的话不知道得背到什么时候,但是Linux中有 Bash 命令历史以及像 apropo
2023-06-28

c#中signalr的使用方法是什么

SignalR 是一个用于实时 web 应用程序的库,可以在客户端和服务器之间实现实时通信。在 C# 中使用 SignalR 有以下几个步骤:引用 SignalR 库:首先需要通过 NuGet 包管理器引用 SignalR 库。可以在 Vi
c#中signalr的使用方法是什么
2024-03-06

c#中epplus的使用方法是什么

EPPlus是一个用于处理Excel文件的开源库,可以在C#中使用。以下是一些EPPlus的使用方法:创建一个新的Excel文件:using OfficeOpenXml;// 创建一个新的Excel文件using (ExcelPackag
c#中epplus的使用方法是什么
2024-03-04

MySQL中explain工具的用法是什么

在MySQL中,EXPLAIN是一种用于查询优化的工具。它可以帮助开发人员和数据库管理员分析查询语句的执行计划,了解MySQL是如何处理查询的。通过EXPLAIN,你可以查看MySQL优化器如何选择并使用索引,以及查询语句中可能存在的性能问
MySQL中explain工具的用法是什么
2024-04-09

c++中precision()的使用方法是什么

在C++中,precision()是用于设置流的精度的函数,通常用于控制浮点数或双精度数的小数位数。它需要与iomanip头文件一起使用。以下是precision()函数的使用方法:#include #include
c++中precision()的使用方法是什么
2024-03-15

c#中class的使用方法是什么

在C#中,class是用来定义对象的模板或蓝图,包含对象的属性和方法。使用class的步骤如下:定义class:首先需要使用关键字“class”来定义一个类,在类的大括号中定义类的成员,如属性和方法。public class Person
c#中class的使用方法是什么
2024-03-12

C#中ManualResetEvent的使用方法是什么

在C#中,ManualResetEvent 是一个同步基元,允许一个线程通知另一个线程,某个事件已经发生。主要有以下几个方法:ManualResetEvent 构造函数:初始化一个 ManualResetEvent 实例,可以指定初始状态。
C#中ManualResetEvent的使用方法是什么
2024-03-08

c#中progressbar的使用方法是什么

在C#中,可以使用ProgressBar控件来显示进度条。以下是ProgressBar控件的使用方法:首先,在窗体的设计器中拖放一个ProgressBar控件到窗体上。设置ProgressBar的属性,比如Minimum、Maximum和V
c#中progressbar的使用方法是什么
2024-03-15

c++中complex的使用方法是什么

在C++中,complex是一个模板类,用于表示复数。它定义在头文件中。以下是complex类的使用方法示例:#include #include int main() {// 创建复数对象std:
c++中complex的使用方法是什么
2024-03-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录