いるProtobufとList <対象> - デシリアライズ/シリアライズする方法?
-
06-09-2019 - |
質問
私は整数、文字列、およびカスタムタイプのような、それ内のオブジェクトのさまざまな種類とList<object>
を持っています。すべてのカスタムタイプがいるProtobuf調整されています。
私は今したいことはprotobuf.netと、このリストをデシリアライズ/シリアライズすることです。今まで私は、これらの混合リスト構築物で、残念ながら不可能な、明示的にそれぞれ、すべての型を宣言しなければならないと思われます。バイナリフォーマッタは何の問題を持っていないので、私は私が何かを逃したことを、あなたは私を助けることができることを願ってこれらの事をします。
だから私の質問は、protobuf.net内のオブジェクトに対処する方法である。
解決
(情報開示:私はいるProtobufネットの著者だ)
BinaryFormatter
は、メタデータに基づくシリアライザあります。すなわちそれは、連載のすべてのオブジェクトに関する.NET型情報を送信します。いるProtobufネット(これも、これを拒否します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);
}
}
}
他のヒント
List<YourClass> list;
ProtoBuf.Serializer.Deserialize<List<YourClass>>(filestream);