No serializer defined for type: System.Windows.Media.Media3D.Point3D

前端 未结 1 1745
青春惊慌失措
青春惊慌失措 2021-01-27 01:19

I am trying to serialize some data using protobuf net. During the serialization I am getting an error that No serialization defined for the type Point3D. I found one issue somet

相关标签:
1条回答
  • 2021-01-27 01:45

    First off, protobuf-net is not a JSON serializer. It serializes from and to "Protocol Buffers" - the binary serialization format used by Google for much of their data communications.

    That being said, there are several solutions to serialize a type, using protobuf-net, that cannot be decorated with ProtoContract attributes:

    1. When contained by some other type, use a proxy or "shim" property as is shown here, OR
    2. Use a surrogate as is shown here, OR
    3. In runtime teach the RuntimeTypeModel about all serializable fields & properties of the type as described here in the section Serializing without attributes.

    For option 2, Since a Point3D is entirely defined by its X, Y and Z coordinates, it's very easy to introduce a serialization surrogate:

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

    And then register it with protobuf-net just once on startup like so:

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

    Alternatively, for option 3, in startup you could define a contract for Point3D like so:

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

    (In my opinion the surrogate is clearer despite requiring more code; defining the protocol entirely in runtime seems too fiddly.)

    I don't recommend option 1 since you would need to add proxy properties to all classes that use Point3D.

    0 讨论(0)
提交回复
热议问题