如何使用protobuf-net代理在继承链中序列化类型
本文关键字:序列化 类型 继承 何使用 protobuf-net 代理 | 更新日期: 2023-09-27 18:11:15
如果您在继承链中有两个(或更多)类(在这种情况下,GeoCoordinate继承自point2d),您如何正确使用代理来允许任何类型的序列化?
作为一个例子,我有这两个代理类 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));
当我尝试序列化这个时,它被序列化为point2d而不是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
根据两个答案得出(谢谢!!)
[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
{
}
您是否尝试在PointF2D
中使用ProtoInclude
来包含GeoCoordinate
?这样的:
[Serializable,
ProtoContract(ImplicitFields = ImplicitFields.AllFields, ImplicitFirstTag = 1),
ProtoInclude(20, "GeoCoordinate")]
public class PointF2D
{
...etc...
}
这应该强制它使用代理SerializableGeoCoordinate
。
所以:你有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);
}
}