Ich habe eine List<object>
mit verschiedenen Arten von Objekten wie Ganzzahlen, Strings und benutzerdefinierten Typen. Alle benutzerdefinierten Typen sind Protobuf-angepasst. Was ich jetzt tun möchte ist, diese Liste mit protobuf.net zu serialisieren/deserialisieren. Bisher vermute ich, dass ich jeden Typ explizit deklarieren muss, was bei diesen Mischlistenkonstrukten leider nicht möglich ist. Da der Binär-Formatierer keine Probleme hat, diese Dinge zu tun, hoffe ich, dass ich etwas verpasst habe und dass du mir helfen kannst. Also meine Frage ist, wie man mit Objekten in protobuf.net umgehen.protobuf und Liste <object> - wie serialisieren/deserialisieren?
Antwort
(Offenlegung: Ich bin der Autor von protobuf-net)
BinaryFormatter
ist ein Metadaten-basierte Serializer; h. es sendet .NET-Typinformationen über jedes serialisierte Objekt. protobuf-net ist ein vertragsbasierter Serializer (das binäre Äquivalent von XmlSerializer
/DataContractSerializer
, das dies ebenfalls ablehnt).
Es gibt keinen aktuellen Mechanismus seit dem anderen Ende für den Transport von beliebigen Objekten, keine Möglichkeit hat zu wissen, was Sie senden ist; Wenn Sie jedoch einen bekannten Satz von verschiedenen Objekttypen haben, die Sie senden möchten, können Optionen vorhanden sein. Es gibt auch Arbeiten in der Pipeline, um Laufzeit-erweiterbare Schemas zu erlauben (und nicht nur Attribute, die beim Build fixiert werden) - aber das ist bei weitem nicht vollständig.
Das ist nicht ideal, aber es funktioniert ... es soll einfacher sein, wenn ich die Arbeit abgeschlossen hat Runtime-Schema zu unterstützen:
using System;
using System.Collections.Generic;
using ProtoBuf;
[ProtoContract]
[ProtoInclude(10, typeof(DataItem<int>))]
[ProtoInclude(11, typeof(DataItem<string>))]
[ProtoInclude(12, typeof(DataItem<DateTime>))]
[ProtoInclude(13, typeof(DataItem<Foo>))]
abstract class DataItem {
public static DataItem<T> Create<T>(T value) {
return new DataItem<T>(value);
}
public object Value {
get { return ValueImpl; }
set { ValueImpl = value; }
}
protected abstract object ValueImpl {get;set;}
protected DataItem() { }
}
[ProtoContract]
sealed class DataItem<T> : DataItem {
public DataItem() { }
public DataItem(T value) { Value = value; }
[ProtoMember(1)]
public new T Value { get; set; }
protected override object ValueImpl {
get { return Value; }
set { Value = (T)value; }
}
}
[ProtoContract]
public class Foo {
[ProtoMember(1)]
public string Bar { get; set; }
public override string ToString() {
return "Foo with Bar=" + Bar;
}
}
static class Program {
static void Main() {
var items = new List<DataItem>();
items.Add(DataItem.Create(12345));
items.Add(DataItem.Create(DateTime.Today));
items.Add(DataItem.Create("abcde"));
items.Add(DataItem.Create(new Foo { Bar = "Marc" }));
items.Add(DataItem.Create(67890));
// serialize and deserialize
var clone = Serializer.DeepClone(items);
foreach (DataItem item in clone) {
Console.WriteLine(item.Value);
}
}
}
Danke Gravell, ich mag deine Arbeit wirklich und hoffe auf eine Antwort direkt von dir. Ich weiß, welche Datentypen in der Liste sind, also bin ich wirklich neugierig auf Ihre Lösung. –
Dank Gravell, können Sie eine Schätzung abgeben, wenn Sie die Unterstützung von Laufzeitschemas abgeschlossen haben? –
würde ich lieber nicht; Ich habe vorher einen Kostenvoranschlag gemacht, und es hat nicht gepasst ... es gibt viele Randfälle, sogar * vor * ich optimiere es. Wenn ich raten müsste, denke ich, dass es noch ein paar Monate dauern wird, bis ich eine gute Freizeitblockade bekomme (was ich nicht erwarte). Ich versuche auch, den "Trunk" mit den neuesten Drahtformat-Änderungen auf dem neuesten Stand zu halten, was die Sache noch lustiger macht. –
List<YourClass> list;
ProtoBuf.Serializer.Deserialize<List<YourClass>>(filestream);
Ist das ein extra '>'? – Robert
(Beispiel hinzugefügt) –
bitte sagen Sie mir auch, wie viel Datenverbrauch es gibt, um eine Liste mit mehr als 10.000 Elementen zu serialisieren? – LoveToCode