2016-07-05 148 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反序列化爲最初序列化的相同類型的對象。