学无先后达者为师!
不忘初心,砥砺前行。

当 .NET 遇上 gRPC:Protobuf 与 C# 数据类型对应表

gRPC 使用 Protobuf 作为其接口定义语言 (IDL)。 消息是 Protobuf 中的主要数据传输对象。 它们在概念上类似于 .NET 类。

syntax = "proto3";

option csharp_namespace = "Contoso.Messages";

message Person {
    int32 id = 1;
    string first_name = 2;
    string last_name = 3;
}

前面的消息定义将三个字段指定为名称/值对。 与 .NET 类型上的属性类似,每个字段都有名称和类型。 字段类型可以是 Protobuf 标量值类型(如 int32),也可以是其他消息。

Protobuf 样式指南建议使用 underscore_separated_names 作为字段名称。 为 .NET 应用创建的新 Protobuf 消息应遵循 Protobuf 样式准则。 .NET 工具会自动生成使用 .NET 命名标准的 .NET 类型。 例如,first_name Protobuf 字段生成 FirstName .NET 属性。

值类型对应表

.proto 类型C# 类型备注
doubledouble
floatfloat
int32int使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint32。
int64long使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint64。
uint32uint
uint64ulong
sint32int使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。
sint64long使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。
fixed32uint
fixed64ulong
sfixed32int总是4个字节。
sfixed64long总是8个字节。
boolbool
stringstring
bytesByteString可能包含任意顺序的字节数据

值类型始终具有默认值,并且该默认值不能设置为 null 。此项约束包括 stringByteString,他们都属于 C# 类。 string 默认为空字符串,ByteString 默认为空字节值。尝试将他们设置为 null 会引发错误。

可为 null 的类型

C# 的 Protobuf 代码生成使用本地类型,如 int 表示 int32。 因此这些值始终包括在内,不能为 null

对于需要显式 null 的值(例如在 C# 代码中使用 int?),Protobuf 的“已知类型”包括编译为可以为 null 的 C# 类型的包装器。 若要使用它们,请将 wrappers.proto 导入到 .proto 文件中,如以下代码所示:

syntax = "proto3"

import "google/protobuf/wrappers.proto"

message Person {
    // ...
    google.protobuf.Int32Value age = 5;
}

wrappers.proto 类型不会在生成的属性中公开。 Protobuf 会自动将它们映射到 C# 消息中相应的可为 null 的 .NET 类型。 例如,google.protobuf.Int32Value 字段生成 int? 属性。 引用类型属性(如 string 和 ByteString )保持不变,但可以向它们分配 null,这不会引发错误。

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
stringgoogle.protobuf.StringValue
ByteStringgoogle.protobuf.BytesValue

集合

列表

Protobuf 中,在字段上使用 repeated 前缀关键字指定列表。

message Person {
    // ...
    repeated string roles = 8;
}

在生成的代码中,repeated 字段由 Google.Protobuf.Collections.RepeatedField<T> 泛型类型表示。

public class Person
{
    // ...
    public RepeatedField<string> Roles { get; }
}

RepeatedField<T> 实现了 IList<T> 接口,因此可以应用 LINQ 查询,或者将其转换为数组或列表。 RepeatedField<T> 属性没有公开的设置器,所以他在内部保证了不可为空。需要向其中添加数据时调用 Add 方法即可:

var person = new Person();

// Add one item.
person.Roles.Add("user");

// Add all items from another collection.
var roles = new [] { "admin", "manager" };
person.Roles.Add(roles);

字典

.NET IDictionary<TKey,TValue> 类型在 Protobuf 中使用 map 表示。

message Person {
    // ...
    map<string, string> attributes = 9;
}

在生成的 .NET 代码中,map 字段由 Google.Protobuf.Collections.MapField<TKey, TValue> 泛型类型表示。 MapField <TKey, TValue> 实现了 IDictionary <TKey, TValue> 接口。 与 repeated 属性一样,map 属性没有公开的设置器 。

var person = new Person();

// Add one item.
person.Attributes["created_by"] = "James";

// Add all items from another collection.
var attributes = new Dictionary<string, string>
{
    ["last_modified"] = DateTime.UtcNow.ToString()
};
person.Attributes.Add(attributes);
赞(4) 打赏
未经允许不得转载:码农很忙 » 当 .NET 遇上 gRPC:Protobuf 与 C# 数据类型对应表

评论 抢沙发

给作者买杯咖啡

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册