初始化为数组的对象的序列化
本文关键字:对象 序列化 数组 初始化 | 更新日期: 2023-09-27 17:54:59
我的问题可能是由于对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只是在这种情况下的错误方法?
您的困难来自XmlSerializer
要求所有类型都被序列化,以便通过反射静态地发现。然而,您的类型MyClass
具有多态object
属性,其中object
的子类型的实例-特别是string []
-正在存储。当XmlSerializer
遇到此异常时,由于不需要此类型的对象,因此序列化器将抛出您所看到的异常。
在序列化诸如此类的多态属性时,有必要使用XML序列化属性来声明可能遇到的类型。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标准属性,允许元素显式断言其类型。它的存在允许XmlSerializer
将XML反序列化为与最初序列化的对象类型相同的对象。(注意,
[XmlInclude(typeof(string))]
似乎是不必要的,因为string
显然是一个内置的已知类型-虽然我找不到证实这一点的文档) -
在多态属性上使用
[XmlElement(String, Type)]
声明可能的多态子类型。因此,您可以这样做:
生成的XML如下所示:public class MyClass { [XmlElement("myObjectString", typeof(string))] [XmlElement("myObjectStringArray", typeof(string[]))] public object myObject { get; set; } public MyClass() { myObject = new string[] { "somestring" }; } }
<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反序列化为与最初序列化的对象类型相同的对象。