У меня есть List<object>
с объектами разных типов, такими как целые числа, строки и настраиваемые типы. Все пользовательские типы настроены на protobuf. Сейчас я хочу сериализовать / десериализовать этот список с помощью protobuf.net. До сих пор я подозреваю, что мне нужно явно объявлять каждый тип, что, к сожалению, невозможно с этими конструкциями смешанного списка. Поскольку у двоичного форматера нет проблем с этим, я надеюсь, что я что-то упустил, и что вы можете мне помочь. Итак, мой вопрос в том, как работать с объектами в protobuf.net.
protobuf и List ‹object› - как сериализовать / десериализовать?
Ответы (2)
(раскрытие: я автор protobuf-net)
BinaryFormatter
- сериализатор на основе метаданных; то есть он отправляет информацию типа .NET о каждом сериализованном объекте. protobuf-net - это сериализатор на основе контрактов (двоичный эквивалент XmlSerializer
/ DataContractSerializer
, который также отклонит это).
В настоящее время не существует механизма для транспортировки произвольных объектов, поскольку другой конец не будет никак узнать, что вы отправляете; однако, если у вас есть известный набор различных типов объектов, которые вы хотите отправить, могут быть варианты. В конвейере также ведется работа по созданию схем, расширяемых во время выполнения (а не только атрибутов, которые фиксируются при сборке), но это далеко не завершено.
Это не идеально, но работает ... будет легче, когда я завершу работу по поддержке схем времени выполнения:
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);
}
}
}
>
?
- person Robert; 02.06.2015