Генерация файла Protobuf-net .proto для наследования

Я создаю прототип Protobuf-net, чтобы заменить часть нашего существующего кода C #, который в настоящее время использует [Datacontract] для сериализации объектов в Xml.

Используя protobuffer, мы можем легко обмениваться данными с Java. Таким образом, я очень заинтересован в создании Protobuf-net файла .proto. Это хорошо сработало почти для всех случаев использования, которые я тестировал до сих пор.

Но теперь с наследованием все по-другому. Файл .proto, созданный для унаследованных классов, очень прост - он не включает ни одно из полей для базового класса.

Само наследование в C # работает нормально - я могу читать сгенерированный поток байтов (см. Мой тест ниже). Итак, внутренний двоичный поток содержит все поля базового класса.

Сгенерированный .proto:

message ProtoScholar {
   optional string Subject = 1;
}

Если я могу понять, как записывается поток байтов, я могу вручную создать соответствующий файл .proto.

У кого-нибудь есть опыт создания файла .proto для наследования с помощью protobuf-net?

Любая информация о том, как создается поток данных для наследования, будет отличной.

Моя модель данных выглядит следующим образом:

[DataContract]
[ProtoInclude(7, typeof(ProtoScholar))]
public class ProtoAlien
{

    [DataMember(Order = 1)]
    public string Name
    {
        get;
        set;
    }


    [DataMember(Order = 2)]
    public double? Average
    {
        get;
        set;
    }

    [DataMember(Order = 3)]
    public int? HowMuch
    {
        get;
        set;
    }

    [DataMember(Order = 4, IsRequired = true)]
    public Height Length
    {
        get; set;
    }


    [DataMember(Order = 5, IsRequired = true)]       
    public Character Personality
    {
        get;
        set;
    }

    [DataMember(Order = 6, IsRequired = true)]       
    public DateTime When
    {
        get; set;
    }

    public enum Height
    {
        Short = 1,
        Medium,
        Tall
    }

    public enum Character : long
    {
        Wasp = 1717986918,
        BumbleBee,
        WorkerBee,
        Hornet,
        Queen
    }        
}

[DataContract()]
public class ProtoScholar : ProtoAlien
{

    [DataMember(Order=1)]
    public string Subject
    {
        get; set;
    }

}

Мой тест NUnit выглядит так:

[Test]
    public void TestInheritanceSupport()
    {

        var protoBuffer = new ProtoScholar
        {
            Name = "Ben11",
            HowMuch = null,
            Length = ProtoAlien.Height.Tall,
            Personality = ProtoAlien.Character.WorkerBee,
            When = new DateTime(2010, 4, 1, 2, 33, 56, 392),
            Subject = "Alien Economics"
        };


        using (var ms = new MemoryStream())
        {

            var proto = Serializer.GetProto<ProtoScholar>();
            Console.WriteLine(proto);

            //Serialize to a Memory Stream
            Serializer.Serialize(ms, protoBuffer);

            Console.WriteLine(ms.Length);
            ms.Position = 0;
            var deserializedProtoBuffer = Serializer.Deserialize<ProtoScholar>(ms);

            Assert.AreEqual("Ben11", deserializedProtoBuffer.Name);

            Assert.Null(deserializedProtoBuffer.HowMuch);
            Assert.AreEqual(ProtoAlien.Height.Tall, deserializedProtoBuffer.Length);

            Assert.AreEqual(ProtoAlien.Character.WorkerBee, deserializedProtoBuffer.Personality);
            Assert.AreEqual(new DateTime(2010, 4, 1, 2, 33, 56, 392), deserializedProtoBuffer.When);
            Assert.AreEqual("Alien Economics", deserializedProtoBuffer.Subject);

        }

    }

person André Vermeulen    schedule 15.09.2010    source источник


Ответы (1)


Поскольку наследование не является частью базовой спецификации, я в основном представляю это с помощью инкапсуляции. Итак, ваш [ProtoInclude] отображается на:

message ProtoAlien {
   // other fields 1 thru 6 [snip]
   optional ProtoScholar ProtoScholar = 7;
}
message ProtoScholar {
   optional string Subject = 1;
}

GetProto<T>() претерпевает капитальный ремонт в версии 2, поэтому он должен поддерживать еще несколько из этих сценариев.

person Marc Gravell    schedule 16.09.2010
comment
Хорошо, я попробую. Подход инкапсуляции имеет смысл при отсутствии базовой спецификации. Но разве не имеет смысла инкапсулировать базовый класс в унаследованный класс? - person André Vermeulen; 16.09.2010
comment
Действительно! Сгенерировал код Java из файлов .proto, и он работает. - person André Vermeulen; 16.09.2010
comment
@ André в общем случае, это создало некоторые проблемы с правильным представлением вещей как их под / супертипа. т.е. если опора SomeBaseType, и вы хотите дать ей экземпляр SomeSuperType. Инкапсулированный из супертипа, мы могли бы знать о SomeBaseType только с точки зрения структуры сообщения. Так что наследование по сети не работает. - person Marc Gravell; 16.09.2010