开发者

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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜