2012-04-20 13 views
3

私はMarc GravellのProtoBuf-netライブラリ(r480、net20)を使用して、既知のタイプの辞書<object, object>を含むカスタムクラスをシリアライズ/デシリアライズします。サーバー/クライアントのシナリオ(両方のC#)で使用されます。
これは、BinaryFormatterを使用した現在のアプローチを置き換えます。
基礎として、私はここで作られた提案を以下のよ: protobuf-and-listobject-how-to-serialize-deserialize、ここprotobuf-and-listobject-how-to-serialize-deserializeを。Protobuf-net:Dictionary <object、object>を含むカスタムクラスをシリアライズ

現在のアプローチは、私がいるProtobufネットに精通誰かが私にそれを改善する方法についてのヒントを与えることができることを願っています、しかし、いくつかの欠点を有しています。 OnSerialising()呼び出しで<ProtoObject, ProtoObject>を辞書に辞書<object, object>

  1. コピー。
  2. 新しいタイプ(それぞれがProtoObject.Create(オブジェクトobj)にProtoIncludeタグと対応するキャストロジックを必要とする)を追加する際のメンテナンスオーバーヘッド
  3. 必要なタイプはすべてProtoObjectによって認識されている必要があります。これにより、プロジェクト間の循環参照の問題が発生しますが、プロジェクト構造のより大きなリファクタリングによって解決することができます。

理想的には私はRuntimeTypeModelのアプローチを使用したいが、私は(クライアントにTypeModel DLLをコンパイルして送信する?)私は種類のクライアントに認識させることができる方法が表示されません。

はまた、最初のトピックでは、マルクGravellは、今後の「ランタイム拡張可能なスキーマは」ものはまだ実装されている場合、誰もが知っている助けることができることを、彼らがどのように機能するかを言及しましたか?
私は私が得るものは何でも応答のために非常に感謝しています、私はもっと何かを明確にすることができますなら、私に知らせてください。
とにかく、彼の素晴らしいライブラリのMarc Gravellに感謝します:)。

ここでは、コードです:あなたがかもしれませんが、単純にDictionary<object,object>をシリアル化

[Serializable] 
[ProtoContract] 
public class Attributes : IXmlSerializable, IEnumerable, IEquatable<Attributes>, ICloneable 
{ 
    // Non ProtoBuf-net relevant code was removed 

    private Dictionary<object, object> attributes = new Dictionary<object, object>(); 

    [ProtoMember(1)] 
    private Dictionary<ProtoObject, ProtoObject> protoDictionary; 

    [OnSerializing] 
    public void OnSerializing(StreamingContext context) 
    { 
     this.protoDictionary = new ProtoDictionary(); 

     foreach (var attribute in attributes) 
     { 
      this.protoDictionary.Add(ProtoObject.Create(attribute.Key), ProtoObject.Create(attribute.Value)); 
     } 
    } 

    [OnDeserialized] 
    public void OnDeserialized(StreamingContext context) 
    { 
     if (this.protoDictionary != null) 
     { 
      this.attributes = new SerializableHashtable(); 

      foreach (var o in this.protoDictionary) 
      { 
       this.attributes.Add(o.Key.Value, o.Value.Value); 
      } 
     } 
    } 
} 

[ProtoContract] 
[ProtoInclude(1, typeof(ProtoObject<bool>))] 
[ProtoInclude(2, typeof(ProtoObject<byte>))] 
[ProtoInclude(3, typeof(ProtoObject<sbyte>))] 
[ProtoInclude(4, typeof(ProtoObject<ushort>))] 
[ProtoInclude(5, typeof(ProtoObject<short>))] 
[ProtoInclude(6, typeof(ProtoObject<uint>))] 
[ProtoInclude(7, typeof(ProtoObject<int>))] 
[ProtoInclude(8, typeof(ProtoObject<ulong>))] 
[ProtoInclude(9, typeof(ProtoObject<long>))] 
[ProtoInclude(10, typeof(ProtoObject<float>))] 
[ProtoInclude(11, typeof(ProtoObject<double>))] 
[ProtoInclude(12, typeof(ProtoObject<decimal>))] 
[ProtoInclude(13, typeof(ProtoObject<string>))] 
[ProtoInclude(20, typeof(ProtoObject<Vector2F>))] 
[ProtoInclude(21, typeof(ProtoObject<Vector3F>))] 
[ProtoInclude(22, typeof(ProtoObject<Shape>))] 
[ProtoInclude(23, typeof(ProtoObject<SharedUser>))] 
[ProtoInclude(24, typeof(ProtoObject<SharedShip>))] 
//[ProtoInclude(25, typeof(ProtoObject<IVehicleConfiguration>))] // Requires Steering dll -> cyclic reference 
[ProtoInclude(26, typeof(ProtoObject<DroneState>))] 
[ProtoInclude(27, typeof(ProtoObject<BuffCode>))] 
[ProtoInclude(28, typeof(ProtoObject<ItemAttribute>))] 
[ProtoInclude(40, typeof(ProtoObject<List<int>>))] 
public abstract class ProtoObject 
{ 
    protected ProtoObject() 
    { 
    } 

    // Replaces public static ProtoObject<T> Create<T>(T value) 
    // in order to use the actual type of the object 
    public static ProtoObject Create(object obj) 
    { 
     if (obj is bool) 
     { 
      return new ProtoObject<bool>((bool)obj); 
     } 

     if (obj is byte) 
     { 
      return new ProtoObject<byte>((byte)obj); 
     } 

     // etc. for all required types 

     return null; 
    } 

    public static ProtoObject Create(bool obj) 
    { 
     TypeModel.Add(obj.GetType(), true); 

     return new ProtoObject<bool>(obj); 
    } 

    public static ProtoObject Create(byte obj) 
    { 
     return new ProtoObject<byte>(obj); 
    } 

    // ... public static ProtoObject Create(type obj) -> for all required types 

    public object Value 
    { 
     get { return ValueImpl; } 
     set { ValueImpl = value; } 
    } 

    protected abstract object ValueImpl { get; set; } 
} 

[ProtoContract] 
public sealed class ProtoObject<T> : ProtoObject 
{ 
    public ProtoObject() 
    { 
    } 

    public ProtoObject(T value) 
    { 
     Value = value; 
    } 

    [ProtoMember(1)] 
    public new T Value { get; set; } 

    protected override object ValueImpl 
    { 
     get { return Value; } 
     set { Value = (T)value; } 
    } 

    public override string ToString() 
    { 
     return Value.ToString(); 
    } 
} 

答えて

1

がサポートユースケースではありません...個人的に、私は、あなたが利用固有のDTOモデルを用いた方がよりを見てすべきだと思います例えば、XmlSerializer,DataContractSerializerまたはJavascriptSerializerを使用している場合。 protobuf-netは依然として最終的に契約シリアライザであり、DTOモデルは理想的なユースケースです。多くの場合、非DTOモデルで動作しますが、これは可能性のあるすべてのモデルで動作するというオープンな保証ではありません。

+0

あなたの答えマルクいただきありがとうございます。私は現在、カスタムシリアル化を実装しています。できる限り、Protobuf-netを使用します。 –

関連する問題