如果在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
答案 0 :(得分: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
{
}
答案 1 :(得分: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);
}
}
答案 2 :(得分:1)
您是否尝试过使用ProtoInclude
中的PointF2D
来加入GeoCoordinate
?像这样:
[Serializable,
ProtoContract(ImplicitFields = ImplicitFields.AllFields, ImplicitFirstTag = 1),
ProtoInclude(20, "GeoCoordinate")]
public class PointF2D
{
...etc...
}
这应该强制它使用代理SerializableGeoCoordinate
。