2016-07-05 138 views
1

我的问题可能是由于对XML序列化的基本误解引起的,但无论如何...
我想序列化一个包含使用XMLSerializer初始化的数组的对象类。最小的例子:XML序列化初始化为数组

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

您是否知道可以预先保存在'myObject'中的所有可能类型的对象? – dbc

+0

向串行化添加数组定义会向xml添加不必要的标记。例如不需要标签:一个。这里没有标签项目: a b c。这两个xml都是vaild。 – jdweng

回答

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反序列化为最初序列化的相同类型的对象。