我的问题可能源于对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只是错误的方法?
答案 0 :(得分:0)
你的困难来自于XmlSerializer
要求所有类型被序列化以通过反射静态发现的事实。但是,您的类型MyClass
具有多态object
属性,其中存储了object
子类型的实例 - 特别是string []
。当XmlSerializer
遇到它时,由于不期望这种类型的对象,序列化程序会抛出您看到的异常。
在序列化诸如此类的多态属性时,必须使用XML serialization attributes来声明可以遇到的类型。 XmlSerializer
提供了两种实现此目的的机制。
使用包含类型的XmlInclude(Type)
属性声明可能的多态子类型。由于string
和string []
是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
显然是一种内置的已知类型 - 虽然我找不到证明这一点的文档。)
在多态属性本身上使用[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反序列化为与最初序列化相同类型的对象。