.netcore grpc的proto文件字段详解

一、.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 attributes = 4;
	map 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);
}
// 服务实现类

    /// 
    /// 字段处理服务
    /// 
    public class ProtoFieldService : FieldRpc.FieldRpcBase
    {
        // 基础配置
        public override async Task 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 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 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 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 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 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();
                if (a is not null)
                {
                    await Console.Out.WriteLineAsync($"A对象:{a.Id}");
                }
            }
            else if (anyObject.Is(B.Descriptor))
            {
                var b = anyObject.Unpack();
                if (b is not null)
                {
                    await Console.Out.WriteLineAsync($"B对象:{b.Id}");
                }
            }
            else if (anyObject.Is(C.Descriptor))
            {
                var c = anyObject.Unpack();
                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 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. 执行过程中,服务端控制台会打印对应的消息

.netcore grpc的proto文件字段详解_第1张图片

        // 基础
        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
    {
        /// 
        /// 根据参数选择不同的方法执行
        /// 
        /// 
        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
            {
                [1] = "one",
                [2] = "two",
                [3] = "three",
                [4] = "four",
                [5] = "five"
            };

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

            var dicDetail = new Dictionary
            {
                [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
            {
               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()
            };
        }
    }

五、执行结果

服务端:

.netcore grpc的proto文件字段详解_第2张图片

.netcore grpc的proto文件字段详解_第3张图片

 客户端:

.netcore grpc的proto文件字段详解_第4张图片

 六、源码地址

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

你可能感兴趣的:(.netcore,rpc)