没有为类型定义序列化程序:System.Windows.Media.Media3D.Point3D

Posted

技术标签:

【中文标题】没有为类型定义序列化程序:System.Windows.Media.Media3D.Point3D【英文标题】:No serializer defined for type: System.Windows.Media.Media3D.Point3D 【发布时间】:2015-11-03 09:47:13 【问题描述】:

我正在尝试使用 protobuf net 序列化一些数据。在序列化过程中,我收到一个错误,即没有为 Point3D 类型定义序列化。我发现了一个类似这样的问题,但仍然无法实施和解决。链接如下:-No serializer defined for type: System.Drawing.Color

[ProtoContract]
public class ReturnPanelData

    [ProtoMember(1)]
    public Point3D PlacedPoint3D  get; set; 
    [ProtoMember(2)]
    public double PlacementAngle  get; set; 
    [ProtoMember(3)]
    public string PanelName  get; set; 

[ProtoContract]
public class ReturnDataType

    [ProtoMember(1)]
    public List<ReturnPanelData> ReturnList  get; set; 
    [ProtoMember(2)]
    public double RemainderArea  get; set; 
    [ProtoMember(3)]
    public int Height  get; set; 
    [ProtoMember(4)]
    public int Width  get; set; 
    [ProtoMember(5)]
    public Point3D BasePoint3D  get; set; 

class Program

    private static HashSet<ReturnDataType> _processedList = new HashSet<ReturnDataType>();
    static void Main(string[] args)
    
        using (var file = File.Create(@"D:\SavedPCInfo2.bin"))
        
            Serializer.Serialize(file, _processedList);
        
        Console.WriteLine("Done");
    

我是 JSON 序列化/反序列化的初学者。如何解决这个问题?

如果无法使用 Protobuf Net 序列化 Point3D,还有哪些其他选项可以序列化/反序列化非常大的列表(大约 300000 个项目)?

【问题讨论】:

为什么不 Newtonsoft.Json? @Rinecamo :在选择序列化技术之前,我搜索了一些文章,发现要序列化/反序列化大列表,使用 Protobuf Net 是一个更好的选择。 ***.com/questions/26368550/… 【参考方案1】:

首先,protobuf-net 不是JSON 序列化程序。它从"Protocol Buffers" 序列化到"Protocol Buffers" - Google 用于大部分数据通信的二进制序列化格式。

话虽如此,有几种解决方案可以使用 protobuf-net 序列化类型,但不能用 ProtoContract 属性修饰:

    当被其他类型包含时,使用代理或“shim”属性,如here 所示,或者 使用here 所示的代理,或者 在运行时向RuntimeTypeModel 教授关于类型的所有可序列化字段和属性,如无属性序列化部分中所述here。

对于选项 2,由于 Point3D 完全由其 X、Y 和 Z 坐标定义,因此很容易引入序列化代理:

[ProtoContract]
struct Point3DSurrogate

    public Point3DSurrogate(double x, double y, double z) : this()
    
        this.X = x;
        this.Y = y;
        this.Z = z;
    

    [ProtoMember(1)]
    public double X  get; set; 
    [ProtoMember(2)]
    public double Y  get; set; 
    [ProtoMember(3)]
    public double Z  get; set; 

    public static implicit operator Point3D(Point3DSurrogate surrogate)
    
        return new Point3D(surrogate.X, surrogate.Y, surrogate.Z);
    

    public static implicit operator Point3DSurrogate(Point3D point)
    
        return new Point3DSurrogate(point.X, point.Y, point.Z);
    

然后在启动时向 protobuf-net 注册一次,如下所示:

ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(Point3D), false).SetSurrogate(typeof(Point3DSurrogate));

或者,对于选项 3,在启动时您可以为 Point3D 定义一个合约,如下所示:

ProtoBuf.Meta.RuntimeTypeModel.Default.Add(typeof(Point3D), true);
ProtoBuf.Meta.RuntimeTypeModel.Default[typeof(Point3D)].Add(1, "X").Add(2, "Y").Add(3, "Z");

(在我看来,尽管需要更多代码,但代理更清晰;完全在运行时定义协议似乎过于繁琐。)

我不推荐选项 1,因为您需要为所有使用 Point3D 的类添加代理属性。

【讨论】:

谢谢先生。你解释的方式很有趣。

以上是关于没有为类型定义序列化程序:System.Windows.Media.Media3D.Point3D的主要内容,如果未能解决你的问题,请参考以下文章

没有为类型定义序列化程序:System.Windows.Media.Media3D.Point3D

protobuf-net 中没有为 System.Version 定义序列化程序

在 JSON 反序列化期间没有为“System.String”类型定义无参数构造函数

更新反序列化JSON对象的属性(没有定义的沙漠类型)

Jackson:为 Map 数据结构注册自定义 XML 序列化程序

Applet(未声明类型为long的静态最终serialVersionUID字段)