Может ли ProtoBuf-Net десериализоваться в плоский класс? - PullRequest
1 голос
/ 13 июля 2011

protobuf-net использует вложенные конструкции protobuf для поддержки наследования.Однако можно ли сделать так, чтобы свойства помещались в плоский целевой класс, имеющий те же свойства, что и унаследованная «сериализованная» версия?

См. Пример теста ниже.Нет необходимости говорить, что результат пространства имен Flat для обоих свойств равен нулю.


Возможное решение: сначала скопируйте данные в flat.B, сначала по каждому свойству.
Примечание: это непредпочтительный вариант.


using System;

namespace hierarchy
{
    using ProtoBuf;

    [ProtoContract]
    public class A
    {
        [ProtoMember(1)]
        public string prop1 { get; set; }
    }

    [ProtoContract]
    public class B : A
    {
        public B()
        {
        }

        [ProtoMember(1)]
        public string prop2 { get; set; }

        public override string ToString()
        {
            return "prop1=" + prop1 + ", prop2=" + prop2;
        }

    }
}

namespace flat
{
    using ProtoBuf;

    [ProtoContract]
    public class B
    {
        [ProtoMember(1)]
        public string prop1 { get; set; }

        [ProtoMember(2)]
        public string prop2 { get; set; }

        public override string ToString()
        {
            return "prop1=" + prop1 + ", prop2=" + prop2;
        }
    }
}

namespace TestProtoSerialization
{
    using ProtoBuf;
    using System.IO;

    public class Test2
    {
        public void Test()
        {
            var hb = new hierarchy.B();
            hb.prop1 = "prop1";
            hb.prop2 = "prop2";

            var ms = new MemoryStream();

            Serializer.Serialize<hierarchy.B>(ms, hb);

            var flatB = Serializer.Deserialize<flat.B>(ms);

            Console.WriteLine(hb.ToString());     // <----- Output: prop1=prop1, prop2=prop2  
            Console.WriteLine(flatB.ToString());  // <----- Output: prop1=, prop2=
        }
    }

    public class Program
    {
        private static void Main(string[] args)
        {
            var o2 = new Test2();
            o2.Test();
        }
    }

}

1 Ответ

2 голосов
/ 13 июля 2011

Не напрямую, и я не уверен, что в этом есть большая необходимость.Возможно, я что-то упускаю в примере ...

Чтобы понять ключевой момент - даже забыв о наследовании, вы нарушили контракт - в вашем примере поля 1 и 1 в одной модели и 1& 2 в другом.

Это действительно зависит от вашей цели;если вы просто хотите передать данные, убедитесь, что вы можете настроить RuntimeTypeModel, которая знает только о производном типе (отключите автоматическую настройку и добавьте поля вручную).Тогда это будет работать только для производного типа (очевидно), но будет выводить данные, как ожидается плоской моделью:

var model = TypeModel.Create();
model.Add(typeof(B), false)
    .Add("prop1", "prop2");

Затем использовать model.Serialize и т. Д.

Однако записьметод плоского преобразования на c # или использование AutoMapper были бы более очевидными.Я бы использовал вышесказанное только в том случае, если моей целью является удаление наследования из выходных данных, например, из соображений совместимости.

...