标量值类型
Protobuf 类型 | C# 类型 |
---|---|
double | double |
float | float |
int32 | int |
int64 | long |
uint32 | uint |
uint64 | ulong |
sint32 | int |
sint64 | long |
fixed32 | uint |
fixed64 | ulong |
sfixed32 | int |
sfixed64 | long |
bool | bool |
string | string |
bytes | ByteString |
标量值始终具有默认值,并且该默认值不能设置为 null
。 此约束包括 string
和 ByteString
,它们都属于 C# 类。 string
默认为空字符串值,ByteString
默认为空字节值。 尝试将它们设置为 null
会引发错误。
日期和时间
本机标量类型不提供与 .NET 的 DateTimeOffset、DateTime 和 TimeSpan 等效的日期和时间值。 可使用 Protobuf 的一些“已知类型”扩展来指定这些类型。 这些扩展为受支持平台中的复杂字段类型提供代码生成和运行时支持。
下表显示日期和时间类型:
.NET 类型 | Protobuf 已知类型 |
---|---|
DateTimeOffset | google.protobuf.Timestamp |
DateTime | google.protobuf.Timestamp |
TimeSpan | google.protobuf.Duration |
可为 null 的类型
C# 的 Protobuf 代码生成使用本机类型,如 int
表示 int32
。 因此这些值始终包括在内,不能为 null
。
下表完整列出了包装器类型以及它们的等效 C# 类型:
C# 类型 | 已知类型包装器 |
---|---|
bool? | google.protobuf.BoolValue |
double? | google.protobuf.DoubleValue |
float? | google.protobuf.FloatValue |
int? | google.protobuf.Int32Value |
long? | google.protobuf.Int64Value |
uint? | google.protobuf.UInt32Value |
ulong? | google.protobuf.UInt64Value |
string | google.protobuf.StringValue |
ByteString | google.protobuf.BytesValue |
字节
Protobuf 支持标量值类型为 bytes
的二进制有效负载。 C# 中生成的属性使用 ByteString
作为属性类型。
使用 ByteString.CopyFrom(byte[] data)
从字节数组创建新实例:
var data = await File.ReadAllBytesAsync(path);
var payload = new PayloadResponse();
payload.Data = ByteString.CopyFrom(data);
使用 ByteString.Span
或 ByteString.Memory
直接访问 ByteString
数据。 或调用 ByteString.ToByteArray()
将实例转换回字节数组:
var payload = await client.GetPayload(new PayloadRequest());
await File.WriteAllBytesAsync(path, payload.Data.ToByteArray());
小数
Protobuf 本身不支持 .NET decimal
类型,只支持 double
和 float
。 在 Protobuf 项目中,我们正在探讨这样一种可能性:将标准 decimal 类型添加到已知类型,并为支持它的语言和框架添加平台支持。 尚未实现任何内容。
可以创建消息定义来表示 decimal
类型,以便在 .NET 客户端和服务器之间实现安全序列化。 但其他平台上的开发人员必须了解所使用的格式,并能够实现自己对其的处理。
为 Protobuf 创建自定义 decimal 类型
package CustomTypes;
// Example: 12345.6789 -> { units = 12345, nanos = 678900000 }
message DecimalValue {
// Whole units part of the amount
int64 units = 1;
// Nano units of the amount (10^-9)
// Must be same sign as units
sfixed32 nanos = 2;
}
nanos
字段表示从 0.999_999_999
到 -0.999_999_999
的值。 例如,decimal
值 1.5m
将表示为 { units = 1, nanos = 500_000_000 }
。 这就是此示例中的 nanos
字段使用 sfixed32
类型的原因:对于较大的值,其编码效率比 int32
更高。 如果 units
字段为负,则 nanos
字段也应为负。
集合
列表
Protobuf 中,在字段上使用 repeated
前缀关键字指定列表
repeated
字段由 Google.Protobuf.Collections.RepeatedField<T>
泛型类型表示。
repeatedField<T>
可实现 IList。 因此你可使用 LINQ 查询,或者将其转换为数组或列表。 RepeatedField<T>
属性没有公共 setter。 项应添加到现有集合中。
字典
.NET IDictionary 类型在 Protobuf 中使用 map<key_type, value_type>
表示。
ap
字段由 Google.Protobuf.Collections.MapField<TKey, TValue>
泛型类型表示。 MapField<TKey, TValue>
可实现 IDictionary。 与 repeated
属性一样,map
属性没有公共 setter。 项应添加到现有集合中。
无结构的条件消息
Protobuf 是一种协定优先的消息传递格式。 构建应用时,必须在 .proto
文件中指定应用的消息,包括其字段和类型。 Protobuf 的协定优先设计非常适合强制执行消息内容,但可能会限制不需要严格协定的情况:
- 包含未知有效负载的消息。 例如,具有可以包含任何消息的字段的消息。
- 条件消息。 例如,从 gRPC 服务返回的消息可能是成功结果或错误结果。
- 动态值。 例如,具有包含非结构化值集合的字段的消息,类似于 JSON。
Protobuf 提供语言功能和类型来支持这些情况。
任意
利用 Any
类型,可以将消息作为嵌入类型使用,而无需 .proto
定义。 若要使用 Any
类型,请导入 any.proto
。
Oneof
oneof
字段是一种语言特性。 编译器在生成消息类时处理 oneof
关键字。 使用 oneof
指定可能返回 Person
或 Error
的响应消息
“值”
Value
类型表示动态类型的值。 它可以是 null
、数字、字符串、布尔值、值字典 (Struct
) 或值列表 (ValueList
)。 Value
是一个 Protobuf 已知类型,它使用前面讨论的 oneof
功能。 若要使用 Value
类型,请导入 struct.proto
。
参考网址:https://learn.microsoft.com/zh-cn/aspnet/core/grpc/protobuf?view=aspnetcore-8.0