【问题标题】:C# XML serialization of derived classes派生类的 C# XML 序列化
【发布时间】:2010-07-25 03:36:45
【问题描述】:

您好,我正在尝试序列化从类派生的对象数组,但我一直使用 c# 遇到相同的错误。非常感谢任何帮助。

很明显,这个例子已经被缩小,以便在现实世界中发布这篇文章。形状将包含大量不同的形状。

程序.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");
        }
    }
}

形状.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(String n, String ns, Shape o, Boolean isNullable, Boolean need 类型)

在 Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterShapeA array.Write3_ArrayOfShape(Object o)

非常感谢

【问题讨论】:

  • 顺便说一句,公共字段通常要避免; public int Size {get;set;} 会更好。
  • 您可以将边缘和大小设置为虚拟get 属性,这样您就不需要存储它们了。跨度>

标签: c# xml class derived


【解决方案1】:
[XmlInclude(typeof(Square))]
public abstract class Shape {...}

(对所有已知的子类型重复)

如果类型仅在运行时已知,您可以将它们提供给XmlSerializer 构造函数,但是:那么缓存和重用该序列化程序实例是重要;否则,您将大量使用动态创建的程序集。当您使用只接受 Type 的构造函数时,它会自动执行此操作,但不会用于其他重载。

【讨论】:

  • 很酷,我想我已经完成了所有工作(现在:S),非常感谢
  • 太棒了,现在我将如何为多个继承的类执行此操作。 (以形状为主题的示例)Shape->Square->ColoredSquare?
  • 您写道:but: **then** it is important to cache and reuse that serializer instance...(我的重点)。您的推理取决于构造函数,而不是动态提供的 Type。还是我错过了什么?
  • @ispiro 是的,构造函数的选择是关键。单参数重载将为相同类型重用生成的程序集。许多其他重载每次调用时都会生成一个动态程序集,即使它与刚才使用的相同。
  • 谢谢。​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​
【解决方案2】:

解决方案:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多