ProtoBuf, inheritance and generics
Given the following code:
[Serializable, ProtoContract]
[ProtoInclude(100, typeof(ValueA))]
[ProtoInclude(101, typeof(ValueB))]
public class Value
{
}
[Serializable, ProtoContract]
public class ValueA : Value
{
}
[Serializable, ProtoContract]
public class ValueB : Value
{
}
[Serializable, ProtoContract]
[ProtoInclude(1000, typeof(ContainerA))]
[ProtoInclude(1001, typeof(ContainerB))]
public class Container<T> where T : Value
{
[ProtoMember(1)]
public T Item;
}
[Serializable, ProtoContract]
public class ContainerA : Container<ValueA>
{
}
[Serializable, ProtoContract]
public class ContainerB : Container<ValueB>
{
}
I get an error when trying to serialize ContainerA/ContainerB:
ProtoBuf.ProtoException : Known-type ContainerB for ProtoIncludeAttribute must be a direct subclass of Container`1
Commenting out one of the following lines - so that only one class inherits from Container - will make ProtoBuf happy again:
[ProtoInclude(1000, typeof(ContainerA))]
[ProtoInclude(1001, typeof(ContainerB))]
What's goi开发者_高级运维ng on here an what can be done about it?
TIA
I'm still waiting for more info, but ultimately inheritance from the open-generic type is a bit tricky. Perhaps if I understand the exact model I could add more, but the following works:
using System.Diagnostics;
using ProtoBuf;
[ProtoContract]
[ProtoInclude(1, typeof(ValueA))]
[ProtoInclude(2, typeof(ValueB))]
public class Value
{
}
[ProtoContract]
public class ValueA : Value
{
}
[ProtoContract]
public class ValueB : Value
{
}
[ProtoContract]
[ProtoInclude(1, typeof(Container<ValueA>))]
[ProtoInclude(2, typeof(Container<ValueB>))]
public abstract class Container
{
public abstract Value BaseValue { get; set; }
}
[ProtoContract]
public class Container<T> : Container where T : Value
{
[ProtoMember(1)]
public T Value { get; set;}
public override Value BaseValue
{
get { return Value; }
set { Value = (T)value; }
}
}
static class Program
{
static void Main()
{
var model = new Container<ValueA>();
model.Value = new ValueA();
var clone = Serializer.DeepClone(model);
Debug.Assert(clone.Value is ValueA);
}
}
although actually the relationship between ValueA
and ValueB
is entirely unnecessary unless you need it:
using System.Diagnostics;
using ProtoBuf;
[ProtoContract]
public class ValueA
{
}
[ProtoContract]
public class ValueB
{
}
[ProtoContract]
[ProtoInclude(1, typeof(Container<ValueA>))]
[ProtoInclude(2, typeof(Container<ValueB>))]
public abstract class Container
{
public abstract object BaseValue { get; set; }
}
[ProtoContract]
public class Container<T> : Container
{
[ProtoMember(1)]
public T Value { get; set;}
public override object BaseValue
{
get { return Value; }
set { Value = (T)value; }
}
}
static class Program
{
static void Main()
{
var model = new Container<ValueA>();
model.Value = new ValueA();
var clone = Serializer.DeepClone(model);
Debug.Assert(clone.Value is ValueA);
}
}
精彩评论