2010-07-24 98 views
12

嗨我想序列化從一個類派生的對象的數組,我不斷使用C#擊中相同的錯誤。任何幫助深表感謝。派生類的C#XML序列化

顯然這個例子已經縮小爲了這篇文章在現實世界中的目的形狀將包含過多的不同形狀。

的Program.cs

namespace XMLInheritTests 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Shape[] a = new Shape[1] { new Square(1) }; 

      FileStream fS = new FileStream("C:\\shape.xml", 
             FileMode.OpenOrCreate); 
      XmlSerializer xS = new XmlSerializer(a.GetType()); 
      Console.WriteLine("writing"); 
      try 
      { 
       xS.Serialize(fS, a); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.InnerException.ToString()); 
       Console.ReadKey(); 
      } 
      fS.Close(); 
      Console.WriteLine("Fin"); 
     } 
    } 
} 

Shape.cs

namespace XMLInheritTests 
{ 
    public abstract class Shape 
    { 
     public Shape() { } 
     public int area; 
     public int edges; 
    } 
} 

Square.cs

namespace XMLInheritTests 
{ 
    public class Square : Shape 
    { 
     public int iSize; 
     public Square() { } 

     public Square(int size) 
     { 
      iSize = size; 
      edges = 4; 
      area = size * size; 
     } 
    } 
} 

錯誤: System.InvalidOperationException:不期望的類型XMLInheritTests.Square。使用XmlInclude或SoapInclude屬性指定靜態未知的類型。

在Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterShapeA rray.Write2_Shape(字符串N,串NS,形狀O,布爾ISNULLABLE,布爾需要 型)

在Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterShapeA rray.Write3_ArrayOfShape(對象o)

非常感謝

+2

作爲一個方面 - 不,公共領域通常是*要避免;一個'public int Size {get; set;}'是更可取的。 – 2010-07-24 19:28:02

+0

你也可以*將邊緣和大小作爲虛擬'get'屬性,這樣你就不需要**存儲它們。 – 2010-07-24 19:28:43

回答

19
[XmlInclude(typeof(Square))] 
public abstract class Shape {...} 

(重複所有已知亞型)

如果僅在運行時才知道類型,則可以將它們提供給構造函數XmlSerializer,但是:然後是重要來緩存並重用該序列化程序實例;否則你會出血動態創建的程序集。當你使用只需要Type的構造函數時,它會自動執行此操作,但不能用於其他重載。

+0

酷我覺得我得到了所有的工作(現在:S),非常感謝 – 111111 2010-07-24 19:36:18

+0

真棒,現在我將如何做到這一點多個繼承類。 (例如與形狀主題保持一致)Shape-> Square-> ColoredSquare? – 2013-02-22 18:29:27

+0

你寫道:'但是:**然後**重要的是緩存和重用序列化程序實例......(我強調)。你的推理依賴於構造函數,而不是動態提供的'Type'。或者我錯過了什麼? – ispiro 2013-12-14 17:57:41

3

解決方案:

class Program 
    { 
     static void Main(string[] args) 
     { 
      Shape[] a = new Shape[2] { new Square(1), new Triangle() }; 

      FileStream fS = new FileStream("C:\\shape.xml",FileMode.OpenOrCreate); 

      //this could be much cleaner 
      Type[] t = { a[1].GetType(), a[0].GetType() }; 


      XmlSerializer xS = new XmlSerializer(a.GetType(),t); 
      Console.WriteLine("writing"); 
      try 
      { 
       xS.Serialize(fS, a); 
      } 
      catch (Exception e) 
      { 
       Console.WriteLine(e.InnerException.ToString()); 
       Console.ReadKey(); 
      } 
      fS.Close(); 
      Console.WriteLine("Fin"); 
     } 
    } 

namespace XMLInheritTests 
{ 
    [XmlInclude(typeof(Square))] 
    [XmlInclude(typeof(Triangle))] 
    public abstract class Shape 
    { 
     public Shape() { } 
     public int area; 
     public int edges; 
    } 
} 

感謝;毫無疑問,我很快會遇到另一個問題:S