Protobuf-zu-C#-Konverter
.proto-Schema einfügen. C#-Klassen mit Auto-Properties zurückbekommen — direkt ins Projekt fallen lassen, ohne protoc-Plugin.
Eingabe (.proto-Schema)
Ausgabe (C#)
Was dieses Tool macht
Du hast ein Protocol Buffers-Schema und einen C#-Service oder -Client, der die passenden DTOs braucht. Der offizielle Weg: protoc mit dem C#-Plugin installieren (oder Grpc.Tools ins .csproj einbinden) und MSBuild beim Build die Partial-Klassen erzeugen lassen. Das funktioniert, ist aber Overkill, wenn du einfach nur das Schema lesen, Typen skizzieren oder eine Message in eine Razor-Seite oder eine einmalige Integration einfügen willst. Dieser Konverter macht dieselbe Art von Arbeit — einfügen, kopieren, in Types.cs ablegen.
Das Type-Mapping ist von der langweilig-aber-korrekten Sorte. string bleibt string (mit Initializer = "", damit Projekte mit nullable Reference Types nicht meckern). bool, int32, int64, uint32, uint64, float, double mappen entsprechend auf bool, int, long, uint, ulong, float, double. bytes wird zu byte[]. repeated T wird zu List<T>, map<K, V> zu Dictionary<K, V>, und Well-Known-Wrapper wie google.protobuf.Timestamp werden als string ausgegeben (proto3 kodiert Timestamps in JSON als RFC 3339, also auf Wire-Ebene einfach ein String — Details siehe proto3-JSON-Spec).
Feldnamen bekommen die Standard-PascalCase-Behandlung — order_id → OrderId, shipping_address → ShippingAddress — passend dazu, was die offizielle C#-protobuf-Referenz erzeugt. Enum-Werte verlieren ihren SCREAMING_SNAKE-Präfix, wenn das Schema der Konvention folgt, jedem Wert den Enum-Namen voranzustellen (also wird ORDER_STATUS_PENDING in enum OrderStatus zu OrderStatus.Pending). Die Ausgabeklassen sind flach — jede verschachtelte Message wird auf die oberste Ebene gehoben, damit du sie aufteilen oder umsortieren kannst, ohne Scopes zu entwirren. Die Konvertierung passiert komplett in deinem Browser; vom Schema wird nichts hochgeladen.
So benutzt du es
Drei Schritte. Die Ausgabe ist kompilierfertig — füge sie einer <code>Types.cs</code>-Datei in deinem Projekt hinzu.
Dein .proto-Schema einfügen
Schema in den linken Editor werfen. syntax = "proto3"; oben ist optional. Der Parser kommt mit verschachtelten message-Blöcken, enum-Deklarationen, oneof, map<K, V>, Feld-Optionen und den üblichen package/import/option-Direktiven klar. imports werden erkannt, aber übersprungen — also importierte Typen inline mit einfügen, falls dein Schema davon abhängt.
Die Feldnamen-Konvertierung ist automatisch: customer_name in .proto wird zu CustomerName in C#. Klassen- und Enum-Namen bleiben wie sie sind (per Konvention bereits PascalCase).
Die Ausgabe lesen
Rechts: public class-Deklarationen mit { get; set; }-Auto-Properties für jede Message, dazu public enum-Deklarationen für jeden Enum. Eine using System.Collections.Generic;-Zeile wird hinzugefügt, wenn das Schema repeated- oder map-Felder verwendet (damit List und Dictionary aufgelöst werden). Datei ins Projekt werfen, in deinen Namespace wickeln, fertig.
Verdrahten
Für reine DTO-Nutzung sind die Klassen serialisierungsfertig mit System.Text.Json oder Newtonsoft.Json. Für echtes gRPC-C#-Arbeiten — Service-Implementierungen, Streaming, Deadlines — weiter Grpc.Tools für die Wire-Format-Typen verwenden und diesen Konverter für handgeschriebene Wrapper, Mapping-Schichten oder Test-Fixtures neben dem generierten Code einsetzen.
Wann das wirklich Zeit spart
DTOs für einen neuen gRPC-Service skizzieren
Du startest einen ASP.NET Core gRPC-Service und willst sehen, wie die Messages in C# aussehen, bevor du dich auf Grpc.Tools festlegst. .proto einfügen, Klassen überfliegen, entscheiden, ob die Feldbenennung zum Stil deines Teams passt, dann die Codegenerierung sauber anschließen.
Handgeschriebene Mapping-Schicht
Deine generierten gRPC-Typen leben in ihrem eigenen Namespace, und du willst schlichte DTOs für die Domain-Schicht. Die Ausgabe hier liefert dir saubere Klassen ohne den Metadaten-Ballast generierten Codes — leicht hin und her zu mappen mit AutoMapper oder selbst geschriebenen Convertern.
Eine Protobuf-Schemaänderung reviewen
Ein Teammitglied hat einer Message in einem PR Felder hinzugefügt. Du willst die Auswirkungen auf die C#-Form sehen, ohne den Branch auszuchecken und einen Build laufen zu lassen. Neues Schema einfügen, gegen die aktuellen C#-Typen diffen, einen fokussierten Review-Kommentar hinterlassen.
Test-Fixtures und schnelle Skripte
Du schreibst ein Einmal-LinqPad-Skript oder eine Konsolen-App, die an ein gRPC-Gateway POSTet. Die komplette Protobuf-Toolchain für 50 Zeilen Testcode aufzusetzen, ist Overkill. Klassen hier abgreifen, JSON-serialisieren, Request abschicken, weitermachen.
Häufige Fragen
Wird mein Schema irgendwohin geschickt?
Nein. Parser und C#-Emitter laufen komplett im Browser als JavaScript. Mach die DevTools auf und beobachte den Network-Tab beim Einfügen — null Requests. Praktisch, wenn dein Schema interne Typnamen, Package-Pfade oder sonst etwas enthält, das du nicht an einen Drittanbieter geben willst.
Funktionieren diese Klassen mit Grpc.Tools-generiertem Code?
Sie produzieren äquivalente Formen, aber nicht byte-genau identische. Grpc.Tools generiert Partial-Klassen, Parser-Registrierungen, Descriptor-Verdrahtung und Vorfahrentypen aus Google.Protobuf.IMessage — nichts davon ist hier dabei. Für echte gRPC-Wire-Protokoll-Arbeit nimm Grpc.Tools. Für reinen DTO-Code (etwa JSON-über-HTTP-Gateways, Mapping-Schichten, Testdaten) reicht diese Ausgabe.
Warum sind int64 und uint64 als long und ulong typisiert statt als string?
Weil sie in C# reinpassen. Anders als JavaScript-Numbers (die oberhalb von 2^53 Präzision verlieren) deckt C# long den vollen int64-Bereich nativ ab, also kein Grund, auf string auszuweichen. Wenn du proto3-JSON deserialisierst, in dem 64-Bit-Ints als Strings ankommen (gemäß JSON-Mapping-Spec), erledigt System.Text.Json mit JsonNumberHandling.AllowReadingFromString die Konvertierung.
Wie wird die SCREAMING_SNAKE-Enum-Wert-Konvention behandelt?
Der Protobuf-Style-Guide empfiehlt, jeden Enum-Wert mit dem Enum-Namen in SCREAMING_SNAKE als Präfix zu versehen. Der Konverter erkennt das und entfernt den Präfix. ORDER_STATUS_UNSPECIFIED in enum OrderStatus wird zu OrderStatus.Unspecified. Folgt dein Enum der Konvention nicht (manche Werte mit Präfix, manche nicht), wird das Stripping übersprungen, und die Werte werden so wie sie sind in PascalCase umgewandelt.
Behandelt es oneof?
Jedes oneof-Feld wird als reguläre Auto-Property ausgegeben. Die Ausgabe erzwingt nicht die "genau eines"-Bedingung, die oneof impliziert — die Sprache C# hat noch keine nativen Discriminated Unions. Wenn du strengere Modellierung brauchst, schau dir Bibliotheken wie OneOf auf NuGet an oder editiere die Ausgabe von Hand zu einer Basisklasse mit Subklassen.
Was ist mit google.protobuf.Timestamp und Well-Known-Types?
Timestamp wird als string ausgegeben (proto3-JSON kodiert Timestamps als RFC-3339-Strings). Empty und Any werden zu object-Platzhaltern — passe sie auf Google.Protobuf.WellKnownTypes.Any oder einen stärkeren Typ an, wenn dein Projekt das WKT-Paket einbindet. Die Ausgabe ist bewusst Framework-frei, damit du sie ohne erzwungene NuGet-Abhängigkeit in jedes C#-Projekt fallen lassen kannst.
Verwandte Tools
Wenn du zwischen Protobuf, JSON und C# jonglierst, passen diese gut zusammen: