C# XML serialization of derived classes

天大地大妈咪最大 提交于 2019-11-26 18:28:26

问题


Hi I am trying to serialize an array of objects which are derived from a class and I keep hitting the same error using c#. Any help is much appreciated.

obviously this example has been scaled down for the purpose of this post in the real world Shape would contain a plethora of different shapes.

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;
        }
    }
}

Error: System.InvalidOperationException: The type XMLInheritTests.Square was not expected. Use the XmlInclude or SoapInclude attribute to specify types that are not known statically.

at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterShapeA rray.Write2_Shape(String n, String ns, Shape o, Boolean isNullable, Boolean need Type)

at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationWriterShapeA rray.Write3_ArrayOfShape(Object o)

Many Thanks


回答1:


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

(repeat for all known subtypes)

If the types are only known at runtime, you can supply them to the XmlSerializer constructor, but: then it is important to cache and reuse that serializer instance; otherwise you will haemorrhage dynamically created assemblies. It does this automatically when you use the constructor that just takes a Type, but not for the other overloads.




回答2:


Solution:

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;
    }
}

Thanks; I no doubt will have another problem very soon :S



来源:https://stackoverflow.com/questions/3326481/c-sharp-xml-serialization-of-derived-classes

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!