XML序列化初始化为数组的对象

时间:2016-07-05 20:55:15

标签: c# arrays xml xml-serialization

我的问题可能源于对XML序列化的基本误解,但无论如何...... 我正在尝试序列化一个包含使用XMLSerializer类使用数组初始化的对象的类。最小的例子:

using System;
using System.IO;
using System.Xml.Serialization;

namespace XMLSerializationTest
{
class Program
{
    static void Main(string[] args)
    {           
        try
        {                
            string xmlFileName = Environment.CurrentDirectory + @"\somename.xml";
            XmlSerializer writer = new XmlSerializer(typeof(MyClass));
            FileStream file = File.Create(xmlFileName);
            MyClass someclass = new MyClass();
            writer.Serialize(file, someclass);
            file.Close();
        }
        catch (Exception exc)
        {
            Console.WriteLine(exc);
        }
        Console.ReadLine();
    }        
}
public class MyClass
{
    public object myObject;
    public MyClass()
    {
        myObject = new string[1] { "somestring" };
    }
}
}

但是,抛出System.InvalidOperationException,读取数组不能在这里使用。它工作正常,如果一个人在MyClass构造函数中替换数组,例如,使用像myObject = "somestring";这样的简单字符串。不幸的是,我只是不知道我的对象是否会提前成为一个阵列。那么有没有可能解决这个问题,例如在这种情况下,使用属性还是XML只是错误的方法?

1 个答案:

答案 0 :(得分:0)

你的困难来自于XmlSerializer要求所有类型被序列化以通过反射静态发现的事实。但是,您的类型MyClass具有多态object属性,其中存储了object子类型的实例 - 特别是string []。当XmlSerializer遇到它时,由于不期望这种类型的对象,序列化程序会抛出您看到的异常。

在序列化诸如此类的多态属性时,必须使用XML serialization attributes来声明可以遇到的类型。 XmlSerializer提供了两种实现此目的的机制。

  1. 使用包含类型的XmlInclude(Type)属性声明可能的多态子类型。由于stringstring []object属性的可能类型,您可以这样做:

    [XmlInclude(typeof(string))]
    [XmlInclude(typeof(string[]))]
    public class MyClass
    {
        public object myObject { get; set; }
    
        public MyClass()
        {
            myObject = new string[] { "somestring" };
        }
    }
    

    结果XML将如下所示:

    <MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <myObject xsi:type="ArrayOfString">
            <string>somestring</string>
        </myObject>
    </MyClass>
    

    注意xsi:type属性?这是一个w3c standard attribute,允许元素显式声明其类型。它的存在允许XmlSerializer将XML反序列化为与最初序列化相同类型的对象。

    (请注意[XmlInclude(typeof(string))]似乎是不必要的,因为string显然是一种内置的已知类型 - 虽然我找不到证明这一点的文档。)

  2. 在多态属性本身上使用[XmlElement(String, Type)]声明可能的多态子类型。因此你会做类似的事情:

    public class MyClass
    {
        [XmlElement("myObjectString", typeof(string))]
        [XmlElement("myObjectStringArray", typeof(string[]))]
        public object myObject { get; set; }
    
        public MyClass()
        {
            myObject = new string[] { "somestring" };
        }
    }
    

    生成的XML看起来像:

    <MyClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
        <myObjectStringArray>
            <string>somestring</string>
        </myObjectStringArray>
    </MyClass>
    

    请注意,myObject元素的名称已修改为传递给[XmlElement(String, Type)]属性构造函数的字符串。这允许XmlSerializer将XML反序列化为与最初序列化相同类型的对象。