protobuf и List <object>- как сериализовать / десериализовать? - PullRequest
6 голосов
/ 29 мая 2009

У меня есть List<object> с различными типами объектов, таких как целые числа, строки и пользовательские типы. Все пользовательские типы настраиваются с протобуфом. Сейчас я хочу сериализовать / десериализовать этот список с protobuf.net. До сих пор я подозреваю, что я должен объявить каждый тип явно, что, к сожалению, невозможно с этими конструкциями смешанного списка. Поскольку у двоичного формирователя нет проблем с этим, я надеюсь, что я что-то пропустил, и вы можете мне помочь. Поэтому мой вопрос заключается в том, как обращаться с объектами в protobuf.net.

Ответы [ 2 ]

11 голосов
/ 29 мая 2009

(раскрытие: я являюсь автором 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);
        }
    }
}
0 голосов
/ 02 июня 2015
List<YourClass> list;
ProtoBuf.Serializer.Deserialize<List<YourClass>>(filestream);
...