ProtoBuf, наследование и дженерики - PullRequest
1 голос
/ 26 мая 2011

С учетом следующего кода:

[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>
{
}

Я получаю сообщение об ошибке при попытке сериализации ContainerA / ContainerB:

ProtoBuf.ProtoException: известный тип ContainerB для ProtoIncludeAttribute должен быть прямым подклассом Container`1

Закомментирование одной из следующих строк - так что только один класс наследует от Container - снова сделает счастливым ProtoBuf:

[ProtoInclude(1000, typeof(ContainerA))]
[ProtoInclude(1001, typeof(ContainerB))]

Что здесь происходит и что с этим можно сделать?

ТИА

1 Ответ

1 голос
/ 27 мая 2011

Я все еще жду дополнительной информации, но в конечном итоге наследование от открытого универсального типа немного сложнее.Возможно, если я понимаю точную модель, я мог бы добавить больше, но работает следующее:

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

, хотя на самом деле отношения между ValueA и ValueB совершенно не нужны, если вам это не нужно:

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