protobuf e List - Como serializar / desserializar?

StackOverflow https://stackoverflow.com/questions/923977

  •  06-09-2019
  •  | 
  •  

Pergunta

Eu tenho um List<object> com diferentes tipos de objetos nele como inteiros, strings e tipos personalizados. Todos os tipos personalizados são ajustados ao protobuf. O que eu quero fazer agora é serializar / desserializar essa lista com protobuf.net. Até agora eu suspeito que eu tenho que declarar todo e qualquer tipo de forma explícita, o que infelizmente não é possível com estas construções-lista mista. Porque o formater binário não tem problemas para fazer essas coisas que eu espero que eu perdi alguma coisa e que você pode me ajudar. Então, minha pergunta é como lidar com objetos em protobuf.net.

Foi útil?

Solução

(divulgação: Eu sou o autor de protobuf-net)

BinaryFormatter é um serializador baseada em metadados; ou seja, ele envia informações do tipo .NET sobre cada objeto serializado. protobuf-net é um serializador baseada em contrato (o equivalente binário do XmlSerializer / DataContractSerializer, que também irá rejeitar este).

Não existe nenhum mecanismo atual para o transporte arbitrária objetos, já que a outra extremidade terão nenhuma maneira de saber o que você está enviando; No entanto, se você tem um conjunto conhecido de diferentes tipos de objeto que você deseja enviar, pode haver opções. Há também o trabalho na calha para permitir esquemas de tempo de execução extensível (em vez de atributos apenas, que são fixados em compilação) -. Mas isso está longe de ser completa


Este não é o ideal, mas funciona ... deve ser mais fácil quando eu tiver concluído o trabalho para apoiar esquemas de tempo de execução:

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);
        }
    }
}

Outras dicas

List<YourClass> list;
ProtoBuf.Serializer.Deserialize<List<YourClass>>(filestream);
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top