.netcore grpc的proto文件字段详解

news2025/1/17 21:41:01

一、.proto文件字段概述

  1. grpc的接口传输参数都是根据.proto文件约定的字段格式进行传输的
  2. grpc提供了多种类型字段;主要包括标量值类型(基础类型)、日期时间、可为null类型、字节、列表、字典、Any类型(任意类型)、Oneof等
  3. 字段严格规范,是一种强类型文件协议

二、案例介绍

  1. 标量值类型
  2. 日期时间
  3. 可为null类型
  4. 字节
  5. 列表
  6. 字典
  7. Any类型
  8. Oneof:一种语言特性,可以通过该特性进行对象切换处理;使用 oneof 指定可能返回 A对象或B对象 的响应消息

三、服务端定义

  1. 定义通用消息实体
  2. 根据不同的类型创建对应的案例实体
  3. 特殊的字段需要导入指定的包才能使用
  4. 定义引用字段的各个服务接口
  5. 内部实现逻辑,及打印展示相应的字段结果
// 1.提供公共的实体proto文件
// 2.服务引用对应的proto文件


// 通用消息文件datamessages.proto
syntax = "proto3";

option csharp_namespace = "GrpcProject";

package grpc.serviceing;

// 基础类型实体
message BaseConfig{
	string name = 1;
	double position = 2;
	float distance= 3 ;
	int32 age = 4;
	int64 timeSpanId = 5;
	uint32 uAge = 6;
	uint64 uTimeSpanId = 7;
	sint32 sAge = 8;
	sint64 sTimeSpanId = 9;
	bool flag = 10;
}


// 日期类型实体 需要导入 日期namespace
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

message DateConfig{
	int64 id = 1;
	google.protobuf.Timestamp dateTimestamp = 2;
	google.protobuf.Duration dateDuration = 3;
}


// 字节类型
message ByteConfig{
	int64 id = 1;
	bytes positionBytes = 2;
}


// 可为null类型 需要导入 null的namespace
import "google/protobuf/wrappers.proto";

message NullConfig{
	int64 id = 1;
	google.protobuf.BoolValue nullBool = 2;
	google.protobuf.DoubleValue nullDoubule = 3;
	google.protobuf.FloatValue nullFloat = 4;
	google.protobuf.Int32Value nullInt = 5;
	google.protobuf.Int64Value nullLong = 6;
	google.protobuf.UInt32Value nullUInt = 7;
	google.protobuf.StringValue nullString = 8;
	google.protobuf.BytesValue nullBytes = 9;
}

//  集合类型
message ListConfig{
	int64 id = 1;
	// 数组
	repeated string names = 2;
	repeated ListDetailConfig details = 3;
	// 字典
	map<int32,string> attributes = 4;
	map<int32,ListDetailConfig> dicDetail = 5;
}

message ListDetailConfig{
	string name = 1;
	int32 height = 2;
}


// 任意类型 需要导入对应的包
import "google/protobuf/any.proto";
message AnyConfig{
	int32 id = 1;
	google.protobuf.Any anyObject = 2;
}

// Oneof类型  编译器在生成消息类时处理 oneof 关键字。 使用 oneof 指定可能返回 A 或 B 或 C 的响应消息
message OneofConfig{
	oneof result{
		A oA = 1;
		B oB = 2;
		C oC = 3;
	}
}

message A{
	int32 id = 1;
}

message B{
	int32 id = 1;
}

message C{
	int32 id =1;
}
// 接口服务定义protofield.proto文件

syntax = "proto3";

import "google/protobuf/empty.proto";
import "Protos/datamessages.proto";

option csharp_namespace = "GrpcProject";

package grpc.serviceing;

service FieldRpc{
	// 基础字段处理
	rpc BaseConfigService(BaseConfig) returns (google.protobuf.Empty);
	// 日期字段处理
	rpc DateConfigService(DateConfig) returns (google.protobuf.Empty);
	// 字节处理
	rpc ByteConfigService(ByteConfig) returns (google.protobuf.Empty);
	// null字段处理
	rpc NullConfigService(NullConfig) returns (google.protobuf.Empty);
	// 集合类型字段处理
	rpc ListConfigService(ListConfig) returns (google.protobuf.Empty);
	// 任意类型字段处理
	rpc AnyConfigService(AnyConfig) returns (google.protobuf.Empty);
	// Oneof类型字段处理
	rpc OneofConfigService(OneofConfig) returns (google.protobuf.Empty);
}
// 服务实现类

    /// <summary>
    /// 字段处理服务
    /// </summary>
    public class ProtoFieldService : FieldRpc.FieldRpcBase
    {
        // 基础配置
        public override async Task<Empty> BaseConfigService(BaseConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------基础配置--------------------------\r\n");
            // 打印字段信息
            var properties = request.GetType().GetProperties();
            foreach (var property in properties)
            {
                var value = property.GetValue(request);

                await Console.Out.WriteLineAsync($"{property.Name}:{value}");
            }
            return new Empty();
        }

        // 日期配置
        public override async Task<Empty> DateConfigService(DateConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------日期配置--------------------------\r\n");
            // timspan
            var duration = request.DateDuration.ToTimeSpan();
            await Console.Out.WriteLineAsync($"{nameof(duration)}:{duration.TotalSeconds}");
            // datetime
            var time = request.DateTimestamp.ToDateTime();
            await Console.Out.WriteLineAsync($"{nameof(time)}:{time:yyyy-MM-dd HH:mm:ss}");

            return new Empty();
        }

        // 字节
        public override async Task<Empty> ByteConfigService(ByteConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------字节配置--------------------------\r\n");

            var bytes = request.PositionBytes.ToByteArray();
            var message = Encoding.UTF8.GetString(bytes, 0, bytes.Length);
            await Console.Out.WriteLineAsync($"{nameof(message)}:{message}");

            return new Empty();
        }
        // null配置
        public override async Task<Empty> NullConfigService(NullConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------null配置--------------------------\r\n");
            // 打印字段信息
            var properties = request.GetType().GetProperties();
            foreach (var property in properties)
            {
                var value = property.GetValue(request);
                var printValue = value == null ? "返回null值" : value;
                await Console.Out.WriteLineAsync($"{property.Name}:{printValue}");
            }

            return new Empty();
        }

        // 集合
        public override async Task<Empty> ListConfigService(ListConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------集合配置--------------------------\r\n");

            var id = request.Id;
            await Console.Out.WriteLineAsync($"主键标识:{id}\r\n");

            // 转换数组array
            await Console.Out.WriteLineAsync($"打印names信息:");
            var names = request.Names.ToArray();
            foreach (var name in names)
            {
                await Console.Out.WriteLineAsync(name);
            }

            // 转换list
            await Console.Out.WriteLineAsync($"\r\n打印detailList信息:");
            var detailList = request.Details.ToList();
            foreach (var item in detailList)
            {
                await Console.Out.WriteLineAsync($"ListDetailConfig:{nameof(item.Name)}  {item.Name};{nameof(item.Height)}  {item.Height}。");
            }

            // 字典

            await Console.Out.WriteLineAsync($"\r\n打印一般字典信息:");
            var dicAttributes = request.Attributes.ToDictionary(t => t.Key, t => t.Value);
            foreach (var attr in dicAttributes)
            {
                await Console.Out.WriteLineAsync($"key:{attr.Key};value:{attr.Value}。");
            }

            await Console.Out.WriteLineAsync($"\r\n打印对象字典信息:");
            foreach (var item in request.DicDetail)
            {
                await Console.Out.WriteLineAsync($"key:{item.Key};value:{item.Value.Name} | {item.Value.Height}。");
            }


            return new Empty();
        }

        // Any
        public override async Task<Empty> AnyConfigService(AnyConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------Any配置--------------------------\r\n");

            var anyObject = request.AnyObject;

            // 检查是否是A对象
            if (anyObject.Is(A.Descriptor))
            {
                var a = anyObject.Unpack<A>();
                if (a is not null)
                {
                    await Console.Out.WriteLineAsync($"A对象:{a.Id}");
                }
            }
            else if (anyObject.Is(B.Descriptor))
            {
                var b = anyObject.Unpack<B>();
                if (b is not null)
                {
                    await Console.Out.WriteLineAsync($"B对象:{b.Id}");
                }
            }
            else if (anyObject.Is(C.Descriptor))
            {
                var c = anyObject.Unpack<C>();
                if (c is not null)
                {
                    await Console.Out.WriteLineAsync($"C对象:{c.Id}");
                }
            }
            else
            {
                await Console.Out.WriteLineAsync("Any未解析到任何对象");
            }


            return new Empty();
        }

        // oneof
        public override async Task<Empty> OneofConfigService(OneofConfig request, ServerCallContext context)
        {
            await Console.Out.WriteLineAsync("\r\n--------------------------Oneof配置--------------------------\r\n");

            // 检测对应的对象是否有值
            switch (request.ResultCase)
            {
                case OneofConfig.ResultOneofCase.None:
                    await Console.Out.WriteLineAsync("未检测到任何对象");
                    break;
                case OneofConfig.ResultOneofCase.OA:
                    await Console.Out.WriteLineAsync($"对象OA存在值:{request.OA.Id}");
                    break;
                case OneofConfig.ResultOneofCase.OB:
                    await Console.Out.WriteLineAsync($"对象OB存在值:{request.OB.Id}");
                    break;
                case OneofConfig.ResultOneofCase.OC:
                    await Console.Out.WriteLineAsync($"对象OC存在值:{request.OC.Id}");
                    break;
                default:
                    break;
            }


            return new Empty();
        }

    }

三、客户端定义

  1. 引用proto文件,配置为客户端类型
  2. 根据编译生成的函数进行传参调用
  3. 创建WPF测试客户端
  4. 各个服务接口创建对应的按钮进行调用
  5. 执行过程中,服务端控制台会打印对应的消息

 

        // 基础
        private async void BtnBaseconfig_Click(object sender, RoutedEventArgs e)
        {
           await WpfFieldClient.Show(1);
            MessageBox();
        }


        // 日期
        private async void BtnDateconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(2);
            MessageBox();
        }

        // 字节
        private async void BtnByteconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(3);
            MessageBox();
        }

        // null
        private async void BtnNullconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(4);
            MessageBox();
        }

        // list
        private async void BtnListconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(5);
            MessageBox();
        }

        // any
        private async void BtnAnyconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(6);
            MessageBox();
        }

        // Oneof
        private async void BtnOneofconfig_Click(object sender, RoutedEventArgs e)
        {
            await WpfFieldClient.Show(7);
            MessageBox();
        }

调用的类库:

    public class WpfFieldClient
    {
        /// <summary>
        /// 根据参数选择不同的方法执行
        /// </summary>
        /// <param name="k"></param>
        public static async Task Show(int k)
        {
            var channel = GrpcChannel.ForAddress("https://localhost:7188");

            var client = new GrpcProject.FieldRpc.FieldRpcClient(channel);
            // 基础
            BaseConfig config = new BaseConfig();
            config.Name = "张三";
            config.Position = 2.33D;
            config.Distance = 5.48F;
            config.Age = 10;
            config.TimeSpanId = 6538590027736100;
            config.SAge = 1921;
            config.STimeSpanId = 6538590027736130;
            config.Flag = true;
            // 日期
            DateConfig dateConfig = new DateConfig();
            dateConfig.Id = 179;
            dateConfig.DateDuration = Duration.FromTimeSpan(TimeSpan.FromSeconds(5));
            // 注意这里的时间是utc时间
            dateConfig.DateTimestamp = Timestamp.FromDateTime(DateTime.UtcNow);

            // 字节
            ByteConfig byteConfig = new ByteConfig();

            byteConfig.Id = 9854564654654;
            byteConfig.PositionBytes = ByteString.CopyFrom(Encoding.UTF8.GetBytes("庄这人的南的很"));

            // null
            NullConfig nullConfig = new NullConfig();
            nullConfig.Id = 1854564654654;
            nullConfig.NullBool = true;
            nullConfig.NullFloat = null;
            nullConfig.NullUInt = null;
            nullConfig.NullInt = 15;
            nullConfig.NullLong = 112345451234787;

            // ListConfig
            ListConfig listConfig = new ListConfig();
            var attributes = new Dictionary<int, string>
            {
                [1] = "one",
                [2] = "two",
                [3] = "three",
                [4] = "four",
                [5] = "five"
            };

            listConfig.Id = 123456456;
            listConfig.Attributes.Add(attributes);

            var dicDetail = new Dictionary<int, ListDetailConfig>
            {
                [1] = new ListDetailConfig { Height = 1, Name = "one" },
                [2] = new ListDetailConfig { Height = 2, Name = "two" },
                [3] = new ListDetailConfig { Height = 3, Name = "three" },
                [4] = new ListDetailConfig { Height = 4, Name = "four" },
                [5] = new ListDetailConfig { Height = 5, Name = "five" }
            };

            listConfig.DicDetail.Add(dicDetail);

            listConfig.Details.Add(new ListDetailConfig { Height = 8, Name = "Eight" });

            var detailConfigs = new List<ListDetailConfig>
            {
               new ListDetailConfig { Height=9,Name="nine"},
               new ListDetailConfig{ Height=10,Name="ten"}
            };

            listConfig.Details.Add(detailConfigs);

            // Any
            AnyConfig anyConfig = new AnyConfig();
            anyConfig.Id = 42564134;

            anyConfig.AnyObject = Any.Pack(new B { Id = 15 });

            // Oneof
            OneofConfig oneofConfig = new OneofConfig();
            oneofConfig.OA = new A { Id = 1 };
            //oneofConfig.OC = new C { Id = 2 };


            var emptyResult = k switch
            {
                1 => await client.BaseConfigServiceAsync(config),
                2 => await client.DateConfigServiceAsync(dateConfig),
                3 => await client.ByteConfigServiceAsync(byteConfig),
                4 => await client.NullConfigServiceAsync(nullConfig),
                5 => await client.ListConfigServiceAsync(listConfig),
                6 => await client.AnyConfigServiceAsync(anyConfig),
                7 => await client.OneofConfigServiceAsync(oneofConfig),
                _ => new Empty()
            };
        }
    }

五、执行结果

服务端:

 

 客户端:

 六、源码地址

链接:https://pan.baidu.com/s/150TKY2Kgln3l_uKAsztyzw 
提取码:hkb9

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/884884.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python文件操作与输入输出:从基础到高级应用

文章目录 &#x1f340;引言&#x1f340;文件操作基础&#x1f340;上下文管理器与文件自动关闭&#x1f340;文件的迭代与逐行读取&#x1f340;文件的其他常见操作&#x1f340;输入输出基础&#x1f340; 文件输入输出&#x1f340;格式化输出&#x1f340;高级文件操作&am…

6---列表

一、有序列表 在文本前面添加数字英文句点&#xff08;.&#xff09;空格可以构成有序列表。如下表&#xff0c;最终生成的列表前面的编号和前面的数字没有绝对关系&#xff0c;总是从第一个数字开始依次增加。&#xff08;和C的枚举有一点点类似&#xff09; 注意&#xff1a;…

解决keep-alive缓存失效问题【必看!!!】

最近正在使用Vue3TsPinia重构后台管理项目&#xff0c;在写到路由缓存时&#xff0c;发现怎么都缓存不了&#xff0c;后来才找到了原因&#xff1a; Vue3中的setup语法糖中的name命名无效 即&#xff1a;如果你是按如下写组件的name&#xff0c;是不起作用的 <script nam…

ARM-M0内核MCU,内置24bit ADC,采样率4KSPS,传感器、电子秤、体脂秤专用,国产IC

ARM-M0内核MCU 内置24bit ADC &#xff0c;采样率4KSPS flash 64KB&#xff0c;SRAM 32KB 适用于传感器&#xff0c;电子秤&#xff0c;体脂秤等等

报名开启 | 2023RflySim暑期学校 : 基于RflySim平台飞控底层算法开发专题培训(第二期)

飞思实验室“基于RflySim平台飞控底层算法开发”系列专题培训第二期开启报名了&#xff01;专题培训由戴训华副教授以及飞思实验室学生&工程师团队主讲&#xff0c;采用“线上线下”集中授课形式&#xff0c;培训时间为8月28日-9月3日&#xff1b;课程内容以RflySim平台介绍…

vite+vue3初始化项目

node环境 14.18&#xff0c;16。最好是16 初始化项目 执行 npm create vuelatest 就是基于vite的命令&#xff0c;执行后会出现以下选择&#xff1a; 目录结构介绍 基本和vue2一个意思 vite.config.js文件如同vue2中的vue.config.js文件&#xff0c;用于配置项目的 安装…

C语言入门 Day_5 四则运算

目录 前言 1.四则运算 2.其他运算 3.易错点 4.思维导图 前言 图为世界上第一台通用计算机ENIAC,于1946年2月14日在美国宾夕法尼亚大学诞生。发明人是美国人莫克利&#xff08;JohnW.Mauchly&#xff09;和艾克特&#xff08;J.PresperEckert&#xff09;。 计算机的最开始…

应用在汽车前照灯系统中的环境光传感芯片

为了保证行车照明的安全性和方便性&#xff0c;减轻驾驶员的劳动强度。近年来&#xff0c;出现了许多新的照明控制系统&#xff0c;例如用于日间驾驶的自动照明系统、光束调节系统、延迟控制等。尤其是汽车自适应前照灯系统&#xff0c;它是一种能够自动改变两种以上的光型以适…

驱动压力P阀10Ω/流量Q阀40Ω比例阀放大器

模块式比例放大器用于控制比例压力流量阀&#xff0c;可驱动PQ比例阀或驱动两路独立控制比例阀&#xff0c;数码管显示现场可设置不同参数&#xff0c;带故障报警提示&#xff0c;DIN35mm导轨安装&#xff0c;24VDC供电&#xff1b;输入指令信号可选0-5V&#xff0c;0-10V&…

线切割数控系统 CAM 功能开发

在第三章我们完成了 Windows CE 系统的的内核定制与软件移植&#xff0c;本实验室开 发的 CAWEP 软件实现了从图形绘制、编辑到运动仿真、代码输出等功能&#xff0c;并未真 正意义上实现线切割机床的控制&#xff0c;本章我们在已有软件的基础上&#xff0c;进行研究与开…

DFT笔记 DC/AC mode与Func

DFT scan可以分为DC和AC两种&#xff0c;区别如下图 DC模式需要ate测试机台提供test clock时钟&#xff08;最快100M&#xff09;&#xff0c;DFT工程师需要升级普通reg变成带si和so&#xff0c;se pin的reg&#xff0c;并插入扫描链&#xff08;scan chain&#xff09;&#x…

系统组件化接口设计

1. 定义这里的系统是指对于一个大系统(如供应链系统)来说划分成的若干小的项目包(如销售管理、采购管理、生产管理)。系统间的接口要讨论的是有关项目包间如何传递数据、数据传递的方式、接口程序及调用方式等问题。2. 原则 保持各项目包间的高度独立性,包括设计的独…

使用wxPython嵌入浏览器加载本地HTML文件

使用wxPython模块嵌入浏览器并加载本地HTML文件的示例博客。以下是一个简单的示例&#xff1a; 介绍&#xff1a; 在本篇博客中&#xff0c;我们将使用Python的wxPython模块来嵌入一个浏览器&#xff0c;并加载一个本地的HTML文件。这对于需要在Python应用程序中显示Web内容…

Visual Studio 2022 中解决使用scanf报错的方法(一劳永逸)

目录 【前言】 一、scanf报错示例 二、解决使用scanf报错的方法 解决方法1&#xff08;不推荐&#xff09; 解决方法2&#xff08;不推荐&#xff09; 解决方法3&#xff08;强烈推荐&#xff09; 第一步 第二步 第三步 三、效果演示&#xff08;方法三&#xff09; …

EF Core+外键

nuget:Microsoft.EntityFrameworkCore.SqlServer Microsoft.EntityFrameworkCore.Tools//这个是反向工程&#xff0c;就是把数据导入到程 1.将数据库各表导入到程式 Scaffold-DbContext Data SourceWAYLIPC;Initial CatalogLabOcr;Persist Security InfoTrue;User IDsa;passw…

加杠杆的股票类型是什么?

加杠杆的股票类型在投资领域有不同的称呼&#xff0c;包括杠杆股票、倍增股票、奇特股票等。这些股票类型都具有共同的特点&#xff0c;即提供给投资者以杠杆交易的机会&#xff0c;可以放大投资的回报。以下是对加杠杆的股票类型的介绍。 1. 杠杆型基金&#xff1a;杠杆型基金…

文件上传第三方存储平台:七牛云对象存储(Java为例)

目录 一、注册账号并创建密钥 二、创建存储空间bucket 三、手动添加文件到存储空间 四、代码中执行上传操作 我发现很多人还不知道对于第三方存储如何在代码中进行使用&#xff0c;而实际开发中很多场景下可能都会遇到。 所以我特别写一篇博客&#xff0c;目的一是方便自己…

idea自动导入包,自动删除包

当我们复制代码时&#xff0c;需要一个个导入包&#xff0c;删除代码时&#xff0c;没有用到的包就没用了&#xff0c;忘记删了就导致代码臃肿了&#xff0c;设置自动导入自动删除包使我们的代码更加简洁。 1、file–>settings 2、找到Auto Import 3、勾选Add unambiguous …

JavaScript实现在线Excel的附件上传与下载

摘要&#xff1a;本文由葡萄城技术团队于CSDN原创并首发。转载请注明出处&#xff1a;葡萄城官网&#xff0c;葡萄城为开发者提供专业的开发工具、解决方案和服务&#xff0c;赋能开发者。 前言 在本地使用Excel时&#xff0c;经常会有需要在Excel中添加一些附件文件的需求&am…

FOSSASIA Summit 2023 - 开源亚洲行

作者 Ted 致歉&#xff1a;本来这篇博客早就该发出&#xff0c;但是由于前几个月频繁差旅导致精神不佳&#xff0c;再加上后续我又参加了 Linux 基金会 7/27 在瑞士日内瓦举办的 Open Source Congress&#xff0c;以及 7/29-30 台北的 COSCUP23&#xff0c;干脆三篇连发&#x…