一、.proto文件字段概述
- grpc的接口传输参数都是根据.proto文件约定的字段格式进行传输的
- grpc提供了多种类型字段;主要包括标量值类型(基础类型)、日期时间、可为null类型、字节、列表、字典、Any类型(任意类型)、Oneof等
- 字段严格规范,是一种强类型文件协议
二、案例介绍
- 标量值类型
- 日期时间
- 可为null类型
- 字节
- 列表
- 字典
- Any类型
- Oneof:一种语言特性,可以通过该特性进行对象切换处理;使用
oneof
指定可能返回 A对象或B对象 的响应消息
三、服务端定义
- 定义通用消息实体
- 根据不同的类型创建对应的案例实体
- 特殊的字段需要导入指定的包才能使用
- 定义引用字段的各个服务接口
- 内部实现逻辑,及打印展示相应的字段结果
// 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();
}
}
三、客户端定义
- 引用proto文件,配置为客户端类型
- 根据编译生成的函数进行传参调用
- 创建WPF测试客户端
- 各个服务接口创建对应的按钮进行调用
- 执行过程中,服务端控制台会打印对应的消息
// 基础
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文章来源:https://www.toymoban.com/news/detail-654508.html
下一篇https://blog.csdn.net/qq_31975127/article/details/132345428文章来源地址https://www.toymoban.com/news/detail-654508.html
到了这里,关于.netcore grpc的proto文件字段详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!