Protobuf-net Serialisierung / Deserialisierung

9

Ich habe überprüft, aber es scheint mir nicht möglich zu sein, zu sehen, wie man eine Klasse direkt in ein Byte-Array serialisiert und anschließend aus einem Byte-Array mit Marc Gravells protobuf-net-Implementierung deserialisiert.

Bearbeiten: Ich habe die Frage geändert und Code zur Verfügung gestellt, weil die ursprüngliche Frage, wie man in Byte [] serialisiert, ohne durch den Stream gehen zu müssen, zugegebenermaßen trivial war. Entschuldigung.

Aktualisierte Frage: Gibt es eine Möglichkeit, sich nicht mit Generika auseinanderzusetzen und stattdessen den Typ der Eigenschaft "MessageBody" durch Reflektion abzuleiten, wenn sie durch den Konstruktor geleitet wird? Ich nehme an, ich kann den Objekttyp nicht serialisieren, richtig? Die aktuelle Lösung sieht sehr umständlich aus, da ich jedes Mal, wenn ich eine neue Nachricht instanziiere, den Typ des MessageBody übergeben muss. Gibt es dafür eine schlankere Lösung?

Ich habe folgendes gefunden:

%Vor%

Was ich gerne bekomme, ist etwas wie:

Nachricht newMsg = neue Nachricht ("Producer", "Consumer", Foo); byte [] byteArray = newMsg.Serialize ();

und Nachricht msg = Message.Deserialize (byteArray);

(wobei Deserialize eine statische Methode ist und immer in ein Objekt vom Typ Nachricht deserialisiert wird und nur wissen muss, in welchen Typ der Nachrichtentext deserialisiert werden soll).

    
Matt Wolf 14.04.2012, 09:33
quelle

2 Antworten

9

Es gibt ein paar verschiedene Fragen hier, also werde ich antworten, was ich sehen kann: Wenn ich etwas verpasst habe, lass es mich wissen.

Erstens, wie bereits erwähnt, ist ein MemoryStream der gebräuchlichste Weg, um zu einem Byte [] zu gelangen. Dies stimmt mit den meisten Serialisierern überein - zum Beispiel haben XmlSerializer, BinaryFormatter und DataContractSerializer auch keine "as a byte [] Überladung", akzeptieren aber MemoryStream.

Generika: Sie müssen keine Generika verwenden; v1 verfügt über Serializer.NonGeneric, wodurch diese von Ihnen entfernt werden. In v2 ist der "Kern" nicht-generisch und kann über RuntimeTypeModel.Default zugegriffen werden; natürlich funktionieren Serializer und Serializer.NonGeneric weiterhin.

Für den Fall, dass der Typ ja enthalten sein muss, nimmt die protobuf-Spezifikation an, dass der Empfänger weiß, welche Art von Daten ihm gegeben werden. Eine einfache Option ist die Verwendung eines einfachen Wrapper-Objekts als "root" -Objekt mit mehreren typisierten Eigenschaften für die Daten (von denen nur eines nicht null ist). Eine weitere Option könnte aus der eingebauten Vererbungsunterstützung über ProtoInclude hervorgehen (Anmerkung: als ein Implementierungsdetail sind diese beiden Ansätze identisch).

Betrachten Sie in Ihrem konkreten Beispiel vielleicht:

%Vor%

Dann einfach mit <Message> serialisieren - die API wird automatisch den richtigen Typ erstellen.

Bei neueren Builds gibt es auch eine DynamicType -Option, die Typdaten für Sie enthält, zum Beispiel:

%Vor%

Dies funktioniert für jeden Wert, der eine Instanz vom Vertragstyp enthält (aber nicht für Primitive und idealerweise ohne Vererbung).

    
Marc Gravell 14.04.2012, 13:06
quelle
3

Der Code, den der OP gepostet hat, würde für mich nicht ganz funktionieren, das Folgende ist eine kleine Anpassung, die Marc Gravells Vorschläge ein wenig mitnimmt. Das Vererben von Message wurde benötigt, um zu verhindern, dass "zyklische Vererbung nicht erlaubt ist", und wie in den Code-Kommentaren unten erwähnt, funktionierte GetBuffer auch nicht.

Ich hoffe, es hilft jemand anderem, nahm mir ein paar Stunden, um alles zum Laufen zu bringen ...

%Vor%     
9swampy 28.01.2014 20:56
quelle