2010-07-24 93 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