Полиморфизм не работает на элементах коллекций с использованием MessagePack-Csharp nuget - PullRequest
0 голосов
/ 15 мая 2018

Я не могу десериализовать коллекцию элементов, где экземпляры имеют отношения наследования между ними.

Кто-нибудь сталкивался с этой проблемой?

Итак, мой вариант использования такой: Моя модель похожа на это:

[DataContract]
    public class Item
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public bool Valid { get; set; }


    }

    [DataContract]
    public class IntermediateItem : Item
    {
        [DataMember]
        public int Priority { get; set; }
    }

    [DataContract]
    public class ExtendedItem : IntermediateItem
    {
        [DataMember]
        public int Count { get; set; }

        [DataMember]
        public ItemsCollection Childs { get; set; }
    }

И коллекция предметов выглядит примерно так:

 [DataContract]
    public class ItemsCollection : Collection<Item>
    {
     }

Настройка, которую я сделал для обеспечения правильной десериализации: Определение CollectionFormatterBase:

 public class ItemCollectionFormatterBase : CollectionFormatterBase<Item, ItemsCollection>
    {
        protected override ItemsCollection Create(int count)
        {
            return new ItemsCollection();
        }

        protected override void Add(ItemsCollection collection, int index, Item value)
        {
            collection.Add(value);
        }
    }

Пример, который не работает и не работает. Я имею в виду, что десериализованные экземпляры имеют базовый тип, то есть как наследование потеряно при сериализации.

Пример:

   MessagePack.Resolvers.CompositeResolver.RegisterAndSetAsDefault(new[] { new ItemCollectionFormatterBase() }, new[] { StandardResolver.Instance });


ExtendedItem instance = new ExtendedItem()
            {
                Id = 1,
                Name = "Extended Item",
                Priority = 121,
                Valid = true,
                Count = 10,
                Childs = new ItemsCollection(new List<Item>() { new Item() { Id = 1 }, new IntermediateItem() { Priority = 10 }, new ExtendedItem() { Count = 10 } })

            };

 byte[] bytes  = MessagePackSerializer.Serialize(instance);

          using (FileStream file = new FileStream(this.filePath.AbsolutePath, FileMode.Create))
            {
                await file.WriteAsync(bytes  , 0, payload.Length);
                await file.FlushAsync();
            }

  using (FileStream file = new FileStream(testsFolder + @"\ExtendedItem.msgPack-csharp.dat", FileMode.Open))
                {

                    file.Seek(0, SeekOrigin.Begin);
                    deserializedInstance =  MessagePackSerializer.Deserialize<ExtendedItem>(file);

                }

глядя на дочерние элементы deserializedInstance, все они относятся к типу элемента. Можете ли вы сказать мне, что я делаю не так? Чего не хватает?

Небольшое обновление относительно определения предмета:

 [DataContract]  
    [KnownType(typeof(IntermediateItem))]
    [KnownType(typeof(ExtendedItem))]
    public class Item
    {
        [DataMember]
        public int Id { get; set; }

        [DataMember]
        public string Name { get; set; }

        [DataMember]
        public bool Valid { get; set; }
    }

Это тоже не работает. (

1 Ответ

0 голосов
/ 15 мая 2018

Хорошо выглядит как статический тип MessagePackSerializer как статический внутренний класс с именем Typeless, и это решает мою проблему:

С экземпляром ExtendedItem:

  ExtendedItem instance = new ExtendedItem()
            {
                Id = 1,
                Name = "Extended Item",
                Priority = 121,
                Valid = true,
                Count = 10,
                Childs = new ItemsCollection(new List<Item>() { new Item() { Id = 1 }, new IntermediateItem() { Priority = 10 }, new ExtendedItem() { Count = 10 } })

            };

Мне удалось сериализовать это и успешно десериализовать!

 byte[] bytes = MessagePackSerializer.Typeless.Serialize(instance);

                await fileManager.WriteAsync(bytes);

                ExtendedItem deserializedInstance = null;

                deserializedInstance = MessagePackSerializer.Typeless.Deserialize(bytes) as ExtendedItem;

несмотря на то, что сериализация и десериализация работали в .NET, этот образец не работал при десериализации в nodejs с пакетом msgpackjs.

...