Freigeben über


Migrieren zu protobuf-net (binär)

Die protobuf-net-Bibliothek ist ein vertragsbasiertes Serialisierungsmodul für .NET, das das binäre Format der Protokollpufferserialization verwendet. Die API folgt typischen .NET-Mustern und ist weitgehend mit XmlSerializer und DataContractSerializer vergleichbar.

Einige Verhaltensweisen und Features von protobuf-net sind bei Migrationen von BinaryFormatter relevant, und viele Szenarien erfordern das Anwenden von Attributen auf Member.

  • Standardmäßig sind sowohl öffentliche als auch nicht öffentliche Typen serialisierbar, wobei das Serialisierungsmodul einen parameterlosen Konstruktor erwartet.
  • protobuf-net erfordert, dass jeder serialisierbare Typ mit dem Attribut [ProtoContract] kommentiert wird. Dieses Attribut kann optional die SkipConstructor = true-Eigenschaft angeben, wodurch kein bestimmter Konstruktor mehr erforderlich ist.
  • Jedes serialisierbare nicht statische Feld und eine Eigenschaft müssen mit dem Attribut [ProtoMember(int identifier)] kommentiert werden. Die Membernamen werden in den Daten nicht codiert. Stattdessen müssen die Benutzer eine positive ganze Zahl auswählen, um die einzelnen Member zu identifizieren. Diese Zahl muss innerhalb dieses Typs eindeutig sein.
  • Die Vererbung muss explizit über das Attribut [ProtoInclude(...)] für jeden Typ mit bekannten Untertypen deklariert werden.
  • Schreibgeschützte Felder werden standardmäßig unterstützt.
  • Alternativ werden einige nicht attribuierte tupelartige Typen anhand von Konstruktormustern erkannt. Ein Typ mit einem Konstruktor mit Parametern, die allen deklarierten öffentlichen Membern entsprechen (nach Name), werden als Tupel interpretiert, und die Parameterreihenfolge wird verwendet, um den Bezeichner für diesen Member abzuleiten.
  • Die Verwendung des Pakets protobuf-net.BuildTools für die Entwurfszeit wird dringend empfohlen. Es bietet Warnungen zur Kompilierungszeit bei häufig auftretenden Fehlern.

Schritt-für-Schritt-Migration

  1. Ermitteln Sie alle Verwendungen von BinaryFormatter.
  2. Stellen Sie sicher, dass die serialization-Codepfade mit Tests abgedeckt sind, um Ihre Änderungen zu überprüfen und um Fehler zu vermeiden.
  3. Installieren Sie das Paket protobuf-net (und optional protobuf-net.BuildTools).
  4. Suchen Sie alle Typen, die mit BinaryFormatter serialisiert werden.
  5. Für Typen, die Sie ändern können:
    • Kommentieren Sie mit dem Attribut [ProtoContract] alle Typen, die mit [Serializable] gekennzeichnet sind, oder implementieren Sie die ISerializable-Schnittstelle. Wenn diese Typen nicht für andere Apps verfügbar gemacht werden (Beispiel: Schreiben einer Bibliothek), die möglicherweise andere Serialisierungsmodule wie DataContractSerializer verwenden, können Sie die Anmerkungen [Serializable] und ISerializable entfernen.
    • Wenden Sie für abgeleitete Typen [ProtoInclude(...)] auf ihre Basistypen an (siehe folgendes Beispiel).
    • Fügen Sie für jeden Typ, der einen Konstruktor deklariert, der Parameter akzeptiert, einen parameterlosen Konstruktor hinzu, oder geben Sie SkipConstructor = true für das Attribut [ProtoContract] an. Geben Sie einen Kommentar ein, der die protobuf-net-Anforderung erläutert (damit sie von niemandem versehentlich entfernt wird).
    • Markieren Sie alle Member (Felder und Eigenschaften), die Sie mit [ProtoMember(int identifier)] serialisieren möchten. Alle Bezeichner müssen innerhalb eines einzelnen Typs eindeutig sein, aber dieselben Zahlen können in Untertypen erneut verwendet werden, wenn die Vererbung aktiviert ist.
  6. Für Typen, die Sie nicht ändern können:
    • Für Typen, die von .NET selbst bereitgestellt werden, können Sie die ProtoBuf.Meta.RuntimeTypeModel.Default.CanSerialize(Type type)-API verwenden, um zu überprüfen, ob sie nativ von protobuf-net unterstützt werden.
    • Sie können dedizierte Datenübertragungsobjekte (Data Transfer Objects, DTO) erstellen und entsprechend zuordnen. (Sie können hierfür den impliziten Umwandlungsoperator verwenden.)
    • Verwenden Sie die RuntimeTypeModel-API, um alles zu definieren, was die Attribute zulassen.
  7. Ersetzen Sie die Nutzung von BinaryFormatter durch ProtoBuf.Serializer.
-[Serializable]
+[ProtoContract]
+[ProtoInclude(2, typeof(Point2D))]
public class Point1D
{
+   [ProtoMember(1)]
    public int X { get; set; }
}

-[Serializable]
+[ProtoContract]
public class Point2D : Point1D
{
+   [ProtoMember(2)]
    public int Y { get; set; }
}