Десериализация объекта (anyType) в документе XML до определенного типа объекта c - PullRequest
0 голосов
/ 14 июля 2020

У меня есть устаревший код, который использовал ArrayList для сериализации данных, это дает xml типов <anyType xsi:type="SomeType">. Все они используют один и тот же тип данных, поэтому это бессмысленно и дает беспорядочный код. * перед десериализацией?

По сути, я хочу превратить код из

[Serializable()]
public class SomeContainer
{
    public ArrayList SomeDataList1
    public ArrayList SomeDataList2
    public ArrayList SomeDataList3
    public ArrayList SomeDataList4
}

в

[Serializable()]
public class SomeContainer
{
    public List<SomeType1> SomeDataList1
    public List<SomeType2> SomeDataList2
    public List<SomeType3> SomeDataList3
    public List<SomeType4> SomeDataList4
}

Так что меня интересует перевод ArrayList -> List , а не контейнер.

Ответы [ 2 ]

2 голосов
/ 14 июля 2020

Если вы отметите свои классы правильными атрибутами XML, вы можете получить свой SomeContainer класс в mimi c поведение ArrayList для десериализации XML.

Вы не можете забота, но вам понадобится реализовать свой класс IEnumerable, если вы также хотите, чтобы ваш класс был сериализован так же, как с ArrayList.

См. пример ниже для полной сериализации / десериализации который выглядит так же, как ArrayList. Если хотите, можете удалить реализацию IEnumerable, и вы увидите, что сериализация изменилась. Однако десериализация с помощью "anyType" по-прежнему работает без реализации IEnumerable.

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Xml.Serialization;

namespace SomeNamespace
{
    [XmlType(nameof(SomeContainer))]
    [XmlInclude(typeof(SomeType))]
    public class SomeContainer : IEnumerable
    {
        [XmlArrayItem(typeof(SomeType))]
        public List<SomeType> SomeDataList = new List<SomeType>();

        public void Add(object o)
        {
            SomeDataList.Add(o as SomeType);
        }

        public int Count()
        {
            return SomeDataList.Count;
        }
        public IEnumerator GetEnumerator()
        {
            return SomeDataList.GetEnumerator();
        }
    }

    public class SomeType
    {
        public string Name { get; set; } = "SomeName";
    }

    class Program
    {

        static void Main()
        {
            SomeContainer s1 = new SomeContainer();
            s1.SomeDataList.Add(new SomeType());
            string tempPath = "c:\\temp\\test.xml";
            XmlSerializer serializer = new XmlSerializer(typeof(SomeContainer));

            // serialize
            using (StreamWriter sw = new StreamWriter(tempPath))
            {
                serializer.Serialize(sw, s1);

            }

            /* Produces the following XML:
                <?xml version="1.0" encoding="utf-8"?>
                <SomeContainer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
                  <anyType xsi:type="SomeType">
                    <Name>SomeName</Name>
                  </anyType>
                </SomeContainer>
            */

            // deserialize
            SomeContainer s2;
            using (StreamReader sr = new StreamReader(tempPath))
            {
                s2 = (SomeContainer)serializer.Deserialize(sr);
            }

            // check contents of s2 as you please
        }
    }
}

(комментарий @ Flydog57 был правильным и появился буквально в тот момент, когда я это набирал.)

0 голосов
/ 14 июля 2020

Что касается комментария, который я оставил для ответа Шона Скелли.

    public class AnyList<T> : IEnumerable where T : class
    {
        List<T> holder = new List<T>();

        public int Count()
        {
            return holder.Count;
        }

        public void Add(object objectToAdd)
        {
            T typedObjectToAdd = objectToAdd as T;
            if (typedObjectToAdd != null)
            {
                holder.Add(typedObjectToAdd);
            }
            // If you can't guarantee the input data, should perhaps inform some data will be skipped.
        }

        public IEnumerator GetEnumerator()
        {
            return holder.GetEnumerator();
        }
    }

И XmlInclude важен, поскольку он может выводить сам по себе, а может и нет, и вместо этого просто проходить через XmlNode, который может быть полезен или не полезен для пользовательских преобразований.

[Serializable()]
[XmlInclude(typeof(SomeType1))]
[XmlInclude(typeof(SomeType2))]
[XmlInclude(typeof(SomeType3))]
[XmlInclude(typeof(SomeType4))]
public class SomeContainer
{
    public AnyList<SomeType1> SomeDataList1
    public AnyList<SomeType2> SomeDataList2
    public AnyList<SomeType3> SomeDataList3
    public AnyList<SomeType4> SomeDataList4
}

Это достаточно чисто, что означает, что я могу вернуться к списку после нормализации данных.

Было бы лучше, если бы C# имел общие атрибуты c.

...