1

如果您在 ineritance 链中有两个(或更多)类(在这种情况下 GeoCoordinate 继承自 PointF2D),您如何正确使用代理项来允许任一类型的序列化?

例如,我有这两个代理类

    public class SerializablePointF2D
    {
        [ProtoMember(1)]
        public double[] Values { get; set; }

        public static implicit operator SerializablePointF2D(PointF2D value)
        {
            return value == null ? null : new SerializablePointF2D {Values = value.ToArrayCopy()} ;
        }`enter code here`
        public static implicit operator PointF2D(SerializablePointF2D value)
        {
            return value == null ? null : new PointF2D(value.Values);
        }
    }
    [ProtoContract]
    public class SerializableGeoCoordinate        {
        [ProtoMember(1)]
        public double[] Values { get; set; }

        public static implicit operator SerializableGeoCoordinate(GeoCoordinate value)
        {
            return value == null ? null : new SerializableGeoCoordinate { Values = value.ToArrayCopy() };
        }
        public static implicit operator GeoCoordinate(SerializableGeoCoordinate value)
        {
            return value == null ? null : new GeoCoordinate(value.Values);
        }
    }

这段代码设置了模型

        var model = TypeModel.Create();
        //GeoCoordinate
        model.Add(typeof(PrimitiveSimpleF2D), false).AddSubType(1, typeof(PointF2D));
        model.Add(typeof(PointF2D), false).AddSubType(4, typeof(GeoCoordinate)).SetSurrogate(typeof(SerializablePointF2D));            
        model.Add(typeof(GeoCoordinate), false).SetSurrogate(typeof(SerializableGeoCoordinate));

当我尝试序列化它时,它会被序列化为 PointF2D 而不是 GeoCoordinate。我已经尝试了我能想到的所有排序组合编辑:基于下面的 Marc 代码,我尝试过

    [ProtoContract]
    public class SerializablePointF2D
    {
        [ProtoMember(1)]
        public double[] Values { get; set; }

        public static implicit operator SerializablePointF2D(PointF2D value)
        {
            if (value == null) return null;
            var geoCoordinate = value as GeoCoordinate;
            if (geoCoordinate != null) return new SerializableGeoCoordinate
            {
                Values = geoCoordinate.ToArrayCopy(),
            };
            return new SerializablePointF2D {Values = value.ToArrayCopy()};
        }
        public static implicit operator PointF2D(SerializablePointF2D value)
        {
            return value == null ? null : new PointF2D(value.Values);
        }
    }
    [ProtoContract]
    public class SerializableGeoCoordinate:SerializablePointF2D
    {

    }

我认为这看起来是对的。它失败了

System.InvalidOperationException : Unexpected sub-type: OsmSharp.Serialization.OsmSharpSerializer+SerializableGeoCoordinate
4

3 回答 3

2

根据两个答案得到它(谢谢!!!)

    [ProtoContract]
    [ProtoInclude(2, typeof(SerializableGeoCoordinate))]
    public class SerializablePointF2D
    {
        [ProtoMember(1)]
        public double[] Values { get; set; }

        public static implicit operator SerializablePointF2D(PointF2D value)
        {
            if (value == null) return null;
            var geoCoordinate = value as GeoCoordinate;
            if (geoCoordinate != null) return new SerializableGeoCoordinate
            {
                Values = geoCoordinate.ToArrayCopy(),
            };
            return new SerializablePointF2D {Values = value.ToArrayCopy()};
        }
        public static implicit operator PointF2D(SerializablePointF2D value)
        {
            if (value == null) return null;
            var geoCoordinate = value as SerializableGeoCoordinate;
            if (geoCoordinate != null)
            {
                return new GeoCoordinate(geoCoordinate.Values);
            }
            return new PointF2D (value.Values );
        }
    }
    [ProtoContract]
    public class SerializableGeoCoordinate:SerializablePointF2D
    {
    }
于 2013-04-27T22:37:31.520 回答
1

所以:你有 3 个不可序列化的类型,你想为它们添加代理?也许这里的诀窍是要意识到 protobuf-net 总是进入任何继承模型的根 - 所以如果在那里声明了一个代理:它会获胜;代理完全接管序列化/反序列化过程。以下通过使代理人模仿原件的继承来工作 - 有什么用?

using ProtoBuf;
using ProtoBuf.Meta;
using System;
public class A
{
    // we'll use this to detect how it was constructed
    public bool ViaOperator { get; set; }

    public int X { get; set; }
}
public class B : A
{
    public int Y { get; set; }
}
public class C : B
{
    public int Z { get; set; }
}


[ProtoContract, ProtoInclude(1, typeof(BSer))]
public class ASer
{
    [ProtoMember(2)] public int X { get; set; }

    protected virtual A ToA()
    {
        return new A { X = X };
    }

    public static implicit operator A(ASer value)
    {
        if (value == null) return null;
        var a = value.ToA();
        a.ViaOperator = true;
        return a;
    }
    public static implicit operator ASer(A value)
    {
        if (value == null) return null;
        var c = value as C;
        if(c != null) return new CSer {
            X = c.X, Y = c.Y, Z = c.Z};
        var b = value as B;
        if(b != null) return new BSer {
            X = b.X, Y = b.Y };
        return new ASer { X = value.X };
    }
}
[ProtoContract, ProtoInclude(1, typeof(CSer))]
public class BSer : ASer
{
    [ProtoMember(2)] public int Y { get; set; }

    protected override A ToA()
    {
        return new B { X = X, Y = Y };
    }
}
[ProtoContract]
public class CSer : BSer
{
    [ProtoMember(2)] public int Z { get; set; }

    protected override A ToA()
    {
        return new C { X = X, Y = Y, Z = Z };
    }
}

static class Program
{
    static void Main()
    {
        var model = TypeModel.Create();
        model.Add(typeof(A), false).AddSubType(2, typeof(B)).SetSurrogate(typeof(ASer));
        model[typeof(B)].AddSubType(2, typeof(C));

        A obj = new B { X = 1, Y = 2 };

        var clone = (B)model.DeepClone(obj);
        Console.WriteLine("{0}, {1}, {2}", clone.X, clone.Y, clone.ViaOperator);

    }
}
于 2013-04-26T21:12:09.480 回答
1

您是否尝试过使用ProtoIncludeinPointF2D来包含GeoCoordinate?像这样:

[Serializable,
ProtoContract(ImplicitFields = ImplicitFields.AllFields, ImplicitFirstTag = 1), 
ProtoInclude(20, "GeoCoordinate")]
public class PointF2D
{
...etc...
}

这应该迫使它使用 surrogate SerializableGeoCoordinate

于 2013-04-26T21:12:34.403 回答