2012-04-20 1 views
3

Я использую библиотеку Marc Gravell's ProtoBuf-net (r480, net20) для сериализации/десериализации пользовательского класса, содержащего словарь <object, object> известных типов, который является используется в сценарии «Сервер/Клиент» (оба C#).
Это заменит наш текущий подход, используя BinaryFormatter.
В качестве основы я следую приведенным здесь предложениям: protobuf-and-listobject-how-to-serialize-deserialize и здесь protobuf-and-listobject-how-to-serialize-deserialize.Protobuf-net: сериализация пользовательского класса, содержащего словарь <объект, объект>

Текущий подход имеет некоторые недостатки, хотя, я надеюсь, что кто-то, более знакомый с Protobuf-net, может дать мне подсказку о том, как его улучшить.

  1. Копирование словаря <object, object> в словарь <ProtoObject, ProtoObject> на вызов OnSerialising().
  2. Накладные расходы на техническое обслуживание при добавлении новых типов (каждый из которых требует тега ProtoInclude и соответствующую логику литья в ProtoObject.Create (объект obj))
  3. Все необходимые типы должны быть известны ProtoObject. Это вызывает циклические эталонные проблемы между проектами, которые могут быть решены только путем более масштабного реорганизации структуры проекта.

В идеале я хотел бы использовать RuntimeTypeModel подход, но я не понимаю, как я могу сделать клиент осведомлен о типах (составление и передачу TypeModel DLL клиенту?).

Также в первой теме Марк Гравелл упомянул, что предстоящие «расширяемые схемы» могут помочь, кто-нибудь знает, реализованы ли они еще и как они работают?
Я очень благодарен за любой ответ, который я получаю, пожалуйста, дайте мне знать, если я смогу прояснить что-то еще.
В любом случае, спасибо Марку Гравелю за его фантастическую библиотеку :).

Вот код:

[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

сериализации Dictionary<object,object> просто не поддерживается вариант использования ... лично я думаю, вы должны смотреть больше в сторону использования использования конкретной модели DTO, как вы могли бы если используется, скажем, XmlSerializer, DataContractSerializer или JavascriptSerializer. protobuf-net по-прежнему в конечном итоге является сериализатором контрактов, а модели DTO - идеальным вариантом использования. Часто он работает с не-DTO-моделями, но это не открытая гарантия того, что он будет работать с каждой моделью, которую можно придумать.

+0

Спасибо за ваш ответ Марк. Я в настоящее время реализую пользовательскую сериализацию и буду использовать Protobuf-net всякий раз, когда могу. –

 Смежные вопросы

  • Нет связанных вопросов^_^