歡迎光臨
每天分享高質量文章

當 .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# 型別 備註
double double
float float
int32 int 使用可變長編碼方式。編碼負數時不夠高效——如果你的欄位可能含有負數,那麼請使用sint32。
int64 long 使用可變長編碼方式。編碼負數時不夠高效——如果你的欄位可能含有負數,那麼請使用sint64。
uint32 uint
uint64 ulong
sint32 int 使用可變長編碼方式。有符號的整型值。編碼時比通常的int32高效。
sint64 long 使用可變長編碼方式。有符號的整型值。編碼時比通常的int64高效。
fixed32 uint
fixed64 ulong
sfixed32 int 總是4個位元組。
sfixed64 long 總是8個位元組。
bool bool
string string
bytes ByteString 可能包含任意順序的位元組資料

值型別始終具有預設值,並且該預設值不能設定為

null

null 。此項約束包括

string

string

ByteString

ByteString,他們都屬於 C# 類。

string

string 預設為空字串,

ByteString

ByteString 預設為空位元組值。嘗試將他們設定為

null

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
string google.protobuf.StringValue
ByteString google.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);
贊(0)

評論 搶沙發

  • 暱稱 (必填)
  • 郵箱 (必填)
  • 網址

分享創造快樂