gpt4 book ai didi

c# - Protobuf-net:序列化包含 Dictionary 的自定义类

转载 作者:行者123 更新时间:2023-11-30 12:49:59 30 4
gpt4 key购买 nike

我正在使用 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 的人能给我一些改进的提示。

  1. 字典复制 <object, object>词典<ProtoObject, ProtoObject>在 OnSerialising() 调用上。
  2. 添加新类型的维护开销(每个都需要 ProtoObject.Create(object obj) 中的 ProtoInclude 标记和相应的转换逻辑)
  3. ProtoObject 必须知道所有必需的类型。这会导致项目之间出现循环引用问题,只能通过对项目结构进行更大规模的重构来解决。

理想情况下,我想使用 RuntimeTypeModel 方法,但我不知道如何让客户端知道类型(编译 TypeModel dll 并将其传输给客户端?)。

同样在第一个主题中,Marc Gravell 提到即将推出的“运行时可扩展模式”可能有所帮助,有人知道这些模式是否已经实现以及它们是如何工作的吗?
我非常感谢收到的任何回复,如果我可以澄清更多内容,请告诉我。
无论如何,感谢 Marc Gravell 提供的精彩图书馆 :)。

代码如下:

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

最佳答案

序列化 Dictionary<object,object>根本不是受支持的用例...就个人而言,我认为您应该更多地关注使用特定于使用的 DTO 模型,就像您可能使用的那样,比如说,XmlSerializer , DataContractSerializerJavascriptSerializer . protobuf-net 最终仍然是一个合约序列化器,DTO 模型是理想的用例。它通常适用于非 DTO 模型,但这并不是公开保证它适用于人们可能设计的每个模型。

关于c# - Protobuf-net:序列化包含 Dictionary<object, object> 的自定义类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10250365/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com