Protobuf-net: serialization of a custom class containing a dictionary <object, object>

I am using the Marc Gravell ProtoBuf-net library (r480, net20) to serialize / deserialize a custom class containing a dictionary of <object, object>known types that is used in a Server / Client script (both C #).
This will replace our current approach using BinaryFormatter.
As a basis, I follow the suggestions made here: protobuf-and-listobject-how-to-serialize-deserialize and here protobuf-and-listobject-how-to-serialize-deserialize .

There are some flaws in the current approach, but I hope someone more familiar with Protobuf-net can give me a hint on how to improve it.

  • Copying a dictionary <object, object>into a dictionary <ProtoObject, ProtoObject>in an OnSerialising () call.
  • Maintenance overhead when adding new types (each of which requires a ProtoInclude tag and the corresponding fill logic in ProtoObject.Create (obj object))
  • All necessary types must be known by ProtoObject. This causes cyclic reference problems between projects, which can only be solved by a more detailed reorganization of the project structure.

Ideally, I would like to use the RuntimeTypeModel approach, but I don’t see how I can inform the client about types (compiling and passing the TypeModel DLL to the client?).

, " " , - , ?
, , , , - . , :).

:

[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();
    }
}
+3
1

Dictionary<object,object> ... , , DTO , , , , XmlSerializer, DataContractSerializer JavascriptSerializer. protobuf-net - , DTO - . -DTO-, , , .

+1

All Articles