Girdi (.proto şeması)

Çıktı (C#)

Bu araç ne yapıyor

Bir Protocol Buffers şeman var ve eşleşen DTO’lara ihtiyaç duyan bir C# servisin ya da istemcin var. Resmi yol protoc’u C# plugin’iyle kurmak (ya da .csproj’una Grpc.Tools’u bağlamak) ve build sırasında MSBuild’in partial sınıfları üretmesine izin vermek. Bu çalışıyor ama sadece şemayı okumak, tipleri zihninde çizmek ya da bir Razor sayfasına ya da bir kerelik entegrasyona mesaj yapıştırmak istediğinde fazla geliyor. Bu dönüştürücü aynı türden işi yapıyor — yapıştır, kopyala, Types.cs’ye bırak.

Tip eşlemesi sıkıcı ama doğru türden. string yine string kalır (nullable-reference projelerinin şikâyet etmemesi için = "" başlatıcısıyla). bool, int32, int64, uint32, uint64, float, double sırasıyla bool, int, long, uint, ulong, float, double’a eşlenir. bytes, byte[] olur. repeated T, List<T>’ye, map<K, V>, Dictionary<K, V>’ye dönüşür ve google.protobuf.Timestamp gibi tanınmış sarmalayıcılar string olarak çıkar (proto3 JSON timestamp kodlaması RFC 3339’dur, wire seviyesinde sadece bir string — ayrıntılar için proto3 JSON spec’ine bak).

Alan adları standart PascalCase muamelesi görür — order_idOrderId, shipping_addressShippingAddressresmi C# protobuf referansının ürettiğinin aynısı. Şema, her enum değerinin önüne enum adını SCREAMING_SNAKE biçiminde koyma alışkanlığını izliyorsa, enum değerleri bu öneki kaybeder (yani enum OrderStatus içindeki ORDER_STATUS_PENDING, OrderStatus.Pending olur). Çıktı sınıfları düzdür — her iç içe mesaj üst seviyeye çekilir, böylece scope’ları sökmeden bölebilir veya yeniden düzenleyebilirsin. Dönüşüm tamamen tarayıcında çalışır; şemaya dair hiçbir şey yüklenmez.

Nasıl kullanılır

Üç adım. Çıktı derlenmeye hazır — projendeki bir <code>Types.cs</code> dosyasına yapıştır.

1

.proto şemanı yapıştır

Şemayı soldaki editöre bırak. En üstteki syntax = "proto3"; isteğe bağlı. Parser iç içe message bloklarını, enum tanımlarını, oneof’u, map<K, V>’yi, alan opsiyonlarını ve sıradan package/import/option direktiflerini ele alır. import’lar tanınır ama atlanır, yani şeman içe aktarılan tiplere bağımlıysa o tipleri de inline yapıştır.

Alan adı dönüşümü otomatik: .proto’daki customer_name, C#’ta CustomerName olur. Sınıf ve enum adları olduğu gibi kalır (gelenekçe zaten PascalCase).

2

Çıktıyı oku

Sağda: her mesaj için { get; set; } auto-property’li public class tanımları, ayrıca her enum için public enum tanımları. Şema repeated veya map alanı kullandığında using System.Collections.Generic; satırı eklenir (List ve Dictionary çözülsün diye). Dosyayı projeye bırak, kendi namespace’ine sar, bitti.

3

Bağla

Saf DTO kullanımı için sınıflar System.Text.Json veya Newtonsoft.Json ile serileştirmeye hazır. Gerçek gRPC C# işleri için — servis implementasyonları, streaming, deadline’lar — wire-format tipleri için Grpc.Tools’u kullanmaya devam et ve bu dönüştürücüyü, üretilen kodun yanında elle yazılmış sarmalayıcılar, mapping katmanları veya test fixture’ları için kullan.

Gerçekten zaman kazandırdığı yerler

Yeni bir gRPC servisi için DTO taslağı

Bir ASP.NET Core gRPC servisi başlatıyorsun ve Grpc.Tools’a bağlanmadan önce mesajların C#’ta nasıl görüneceğini görmek istiyorsun. .proto’yu yapıştır, sınıflara göz at, alan adlandırması ekibinin tarzına uyuyor mu karar ver, sonra codegen’i düzgünce kur.

Elle yazılan mapping katmanı

Üretilmiş gRPC tiplerin kendi namespace’lerinde yaşıyor ve domain katmanın için sade DTO’lar istiyorsun. Buradaki çıktı, üretilmiş kodun metadata gürültüsü olmadan temiz sınıflar verir — AutoMapper veya elle yazılmış dönüştürücülerle iki yönlü map etmek kolay.

Bir Protobuf şema değişikliğini gözden geçirmek

Ekip arkadaşın bir PR’da bir mesaja alanlar ekledi. Branch’i çekip build çalıştırmadan C# tarafındaki etkisini görmek istiyorsun. Yeni şemayı yapıştır, mevcut C# tipleriyle diff al, odaklı bir review yorumu bırak.

Test fixture’ları ve hızlı script’ler

Tek seferlik bir LinqPad script’i ya da bir gRPC-gateway’e POST atan bir konsol uygulaması yazıyorsun. 50 satır test kodu için tüm Protobuf toolchain’ini kurmak fazla. Sınıfları buradan al, JSON’a serileştir, isteği gönder, yoluna devam et.

Sık sorulan sorular

Şemam bir yere gönderiliyor mu?

Hayır. Parser ve C# emitter tamamen tarayıcında JavaScript olarak çalışır. Yapıştırırken DevTools’u aç ve Network sekmesini izle — sıfır istek. Şeman dahili tip adları, package yolları veya üçüncü tarafa göndermek istemediğin başka bir şey içerdiğinde işe yarar.

Bu sınıflar Grpc.Tools tarafından üretilmiş kodla çalışır mı?

Eşdeğer şekiller üretirler ama bayt bayt aynı değiller. Grpc.Tools partial sınıflar, parser kayıtları, descriptor bağlantıları ve Google.Protobuf.IMessage’tan ata tipler üretir — burada bunların hiçbiri yok. Gerçek gRPC wire protokol işleri için Grpc.Tools’u kullan. Sadece DTO kodu için (örneğin JSON-over-HTTP gateway’ler, mapping katmanları, test verisi) bu çıktı yeterli.

int64 ve uint64 neden string yerine long ve ulong olarak tipleniyor?

Çünkü C#’ta sığıyorlar. JavaScript Number’larının (2^53 üstünde hassasiyetini kaybeden) aksine, C#’taki long tüm int64 aralığını native olarak işler, yani string’e geri düşmek için bir sebep yok. 64-bit int’lerin string olarak geldiği proto3 JSON’ı deserialize ediyorsan (JSON mapping spec’i’ne göre), JsonNumberHandling.AllowReadingFromString ile System.Text.Json dönüşümü hallediyor.

SCREAMING_SNAKE enum değer geleneğini nasıl ele alıyor?

Protobuf style guide her enum değerinin önüne enum adını SCREAMING_SNAKE biçiminde eklemeyi önerir. Dönüştürücü bunu algılar ve kaldırır. OrderStatus enum’undaki ORDER_STATUS_UNSPECIFIED, OrderStatus.Unspecified olur. Enum’un bu kurala uymuyorsa (bazı değerler önekli, bazıları değil), önek temizleme atlanır ve değerler olduğu gibi PascalCase yapılır.

oneof’u kaldırıyor mu?

Bir oneof’un her alanı normal bir auto-property olarak çıkar. Çıktı, oneof’un ima ettiği "tam olarak bir tane" kısıtını zorlamaz — C# dilinin henüz native discriminated union’ı yok. Daha sıkı modelleme istiyorsan NuGet’teki OneOf gibi kütüphanelere bak ya da çıktıyı elle düzenleyip taban sınıf + alt sınıflar yap.

google.protobuf.Timestamp ve well-known type’lar ne olacak?

Timestamp string olarak çıkar (proto3 JSON timestamp’leri RFC 3339 string’i olarak kodlar). Empty ve Any, object placeholder’ı olur — projeniz WKT paketini çekiyorsa Google.Protobuf.WellKnownTypes.Any’ye veya daha güçlü bir tipe çevir. Çıktı bilerek framework’süz; herhangi bir C# projesine NuGet bağımlılığı dayatmadan bırakabilirsin.

İlgili araçlar

Protobuf, JSON ve C# arasında gidip geliyorsan bunlar iyi gider: