C# 反序列化';对象';(anyType)在XML文档中指定为特定的对象类型

C# 反序列化';对象';(anyType)在XML文档中指定为特定的对象类型,c#,deserialization,C#,Deserialization,我有一些使用ArrayList序列化数据的遗留代码,这会产生的xml类型。它们都共享相同的数据类型,因此毫无意义,生成的代码乱七八糟 在反序列化时,除了在反序列化xml之前对其进行预清理外,是否有任何优雅的方法将此类数据强制放入列表中 基本上,我想把代码从 [Serializable()] public class SomeContainer { public ArrayList SomeDataList1 public ArrayList SomeDataList2 p

我有一些使用ArrayList序列化数据的遗留代码,这会产生
的xml类型。它们都共享相同的数据类型,因此毫无意义,生成的代码乱七八糟

在反序列化时,除了在反序列化xml之前对其进行预清理外,是否有任何优雅的方法将此类数据强制放入列表中

基本上,我想把代码从

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

[Serializable()]
公共类容器
{
公共列表SomeDataList1
公共列表SomeDataList2
公共列表SomeDataList3
公共列表SomeDataList4
}

因此,我对ArrayList->List转换感兴趣,而不是容器。

如果您用正确的XML属性标记类,您可以让您的
SomeContainer
类模仿
ArrayList
反序列化XML的行为

您可能不在乎,但如果您还希望将类序列化为与ArrayList相同的格式,则需要让类实现
IEnumerable

有关与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
        }
    }
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.IO;
使用System.Xml.Serialization;
名称空间名称空间
{
[XmlType(nameof(SomeContainer))]
[xmlclude(typeof(SomeType))]
公共类SomeContainer:IEnumerable
{
[XmlArrayItem(typeof(SomeType))]
public List SomeDataList=新列表();
公共无效添加(对象o)
{
添加(o作为SomeType);
}
公共整数计数()
{
返回SomeDataList.Count;
}
公共IEnumerator GetEnumerator()
{
返回SomeDataList.GetEnumerator();
}
}
公共类SomeType
{
公共字符串名称{get;set;}=“SomeName”;
}
班级计划
{
静态void Main()
{
SomeContainer s1=新的SomeContainer();
s1.SomeDataList.Add(newsometype());
字符串tempPath=“c:\\temp\\test.xml”;
XmlSerializer serializer=新的XmlSerializer(typeof(SomeContainer));
//连载
使用(StreamWriter sw=新StreamWriter(tempPath))
{
序列化器。序列化(sw,s1);
}
/*生成以下XML:
名字
*/
//反序列化
SomeContainer s2;
使用(StreamReader sr=新的StreamReader(tempPath))
{
s2=(SomeContainer)序列化程序。反序列化(sr);
}
//请检查s2的内容
}
}
}

(@Flydog57的评论是对的,我在键入时就这么说了。)

如果你用正确的XML属性标记你的类,你可以让你的
SomeContainer
类模仿
ArrayList
反序列化XML的行为

您可能不在乎,但如果您还希望将类序列化为与ArrayList相同的格式,则需要让类实现
IEnumerable

有关与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
        }
    }
}
使用系统;
使用系统集合;
使用System.Collections.Generic;
使用System.IO;
使用System.Xml.Serialization;
名称空间名称空间
{
[XmlType(nameof(SomeContainer))]
[xmlclude(typeof(SomeType))]
公共类SomeContainer:IEnumerable
{
[XmlArrayItem(typeof(SomeType))]
public List SomeDataList=新列表();
公共无效添加(对象o)
{
添加(o作为SomeType);
}
公共整数计数()
{
返回SomeDataList.Count;
}
公共IEnumerator GetEnumerator()
{
返回SomeDataList.GetEnumerator();
}
}
公共类SomeType
{
公共字符串名称{get;set;}=“SomeName”;
}
班级计划
{
静态void Main()
{
SomeContainer s1=新的SomeContainer();
s1.SomeDataList.Add(newsometype());
字符串tempPath=“c:\\temp\\test.xml”;
XmlSerializer serializer=新的XmlSerializer(typeof(SomeContainer));
//连载
使用(StreamWriter sw=新StreamWriter(tempPath))
{
序列化器。序列化(sw,s1);
}
/*生成以下XML:
名字
*/
//反序列化
SomeContainer s2;
使用(StreamReader sr=新的StreamReader(tempPath))
{
s2=(SomeContainer)序列化程序。反序列化(sr);
}
//请检查s2的内容
}
}
}

(@Flydog57的评论是对的,当我输入这段文字的时候,它就出现了。)

关于我为肖恩·斯凯利的答案留下的评论

    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();
        }
    }
public class AnyList:IEnumerable其中T:class
{
列表持有者=新列表();
公共整数计数()
{
报税表持有人。计数;
}
public void Add(对象objectToAdd)
{
T typedObjectToAdd=对象toadd为T;
[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
}