XML 初始化为数组的对象的序列化
XML Serialization of an object initialized as array
我的问题可能是由于对 XML 序列化的基本误解引起的,但无论如何...
我正在尝试序列化一个 class,其中包含一个使用 XMLSerializer class 用数组初始化的对象。最小示例:
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,这里不能使用读数组。如果用 myObject = "somestring";
这样的简单字符串替换 MyClass 构造函数中的数组,它工作正常。不幸的是,我只是不知道我的对象是否会预先是一个数组。那么有没有可能解决这个问题,例如有属性还是 XML 在这种情况下只是错误的方法?
你的困难来自这样一个事实,即 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
attribute? That is a 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 反序列化为与最初序列化相同类型的对象。
我的问题可能是由于对 XML 序列化的基本误解引起的,但无论如何...
我正在尝试序列化一个 class,其中包含一个使用 XMLSerializer class 用数组初始化的对象。最小示例:
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,这里不能使用读数组。如果用 myObject = "somestring";
这样的简单字符串替换 MyClass 构造函数中的数组,它工作正常。不幸的是,我只是不知道我的对象是否会预先是一个数组。那么有没有可能解决这个问题,例如有属性还是 XML 在这种情况下只是错误的方法?
你的困难来自这样一个事实,即 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
attribute? That is a 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 反序列化为与最初序列化相同类型的对象。