简体   繁体   English

XmlSerializer反序列化类层次结构

[英]XmlSerializer deserialize class hierarchy

I got some issues with the XmlSerializer in .NET. .NET中的XmlSerializer出现了一些问题。

Here I have a small example I built up just right now. 这里有一个我刚刚建立的小例子。 (also available @ gist https://gist.github.com/2d84be9041a3f9c06237 ) (也可通过@ gist https://gist.github.com/2d84be9041a3f9c06237获得

using System.IO;
using System.Xml.Serialization;

namespace XmlSerializingSample
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            var specialType = new SpecialType()
                {
                    Id = 1,
                    Name = "test"
                };

            var serializer = new XmlSerializer(typeof (SpecialType));
            var des = new XmlSerializer(typeof (BaseType));
            using (var memeStream = new MemoryStream())
            {
                serializer.Serialize(memeStream, specialType);
                memeStream.Flush();

                memeStream.Seek(0, SeekOrigin.Begin);
                var instance = des.Deserialize(memeStream); // Here it throws the exception
            }
        }
    }

    [XmlInclude(typeof(SpecialType))]
    [XmlType("baseType")]
    public class BaseType
    {
        public long Id { get; set; }
    }

    [XmlRoot("special")]
    public class SpecialType : BaseType
    {
        public string Name { get; set; }
    }
}

In line 24 of the code I get an InvalidOperationException stating "{"<special xmlns=''> wurde nicht erwartet."}" [yes, it's german] 在代码的第24行中,我得到一个InvalidOperationException,它声明“ {“ <特殊xmlns =''> wurde nicht erwartet。”}“ [是的,它是德语]

All Posts I found stated, after adding XmlIncludeAttribute on the base type being deserialized, this should work. 我发现的所有文章都说过,在要反序列化的基本类型上添加XmlIncludeAttribute之后,这应该可以工作。 Did I forget sth.? 我忘了……吗?

Regards, MacX 问候,MacX

The problem is that your Serializer is serializing the SpecialType with a root element as so: 问题是您的序列化程序正在使用根元素将SpecialType序列化为:

<special ...>
   <Id>...

But then you try to Deserialize it using var des = new XmlSerializer(typeof (BaseType)); 但是,然后您尝试使用var des = new XmlSerializer(typeof (BaseType));将其反序列化var des = new XmlSerializer(typeof (BaseType)); it knows about both types but it doesn't know how to handle the root element in the xml. 它知道这两种类型,但不知道如何处理xml中的root元素。

If you want this to work, you need to also set the root element of the base type to serialize as special . 如果您希望这样做,还需要设置基本类型的根元素以序列化为special In other words, you would need to do this: 换句话说,您需要执行以下操作:

[XmlInclude(typeof(SpecialType))]
[XmlType("baseType")]
[XmlRoot("special")]
public class BaseType
{
      public long Id { get; set; }
}

That way, the deserializer knows how to handle special as the root element. 这样,解串器便知道如何将special作为根元素处理。

I don't think there are other simple alternatives to make this work out of the box. 我认为没有其他简单的替代方法可以使这项工作立即可用。

Update 更新

This is another alternative using the XmlAttributeOverrides class. 这是使用XmlAttributeOverrides类的另一种选择。

LinqPad code: LinqPad代码:

void Main()
{
      var specialType = new SpecialType()
                {
                    Id = 1,
                    Name = "test"
                };

            var serializer = new XmlSerializer(typeof (SpecialType));

            XmlAttributeOverrides attrOverrides = new XmlAttributeOverrides();
            XmlAttributes attrs = new XmlAttributes();

            // Create an XmlRootAttribute to override.
            XmlRootAttribute attr = new XmlRootAttribute();
            attr.ElementName = "special";

            // Add the XmlRootAttribute to the collection of objects.
            attrs.XmlRoot=attr; 
            attrOverrides.Add(typeof(BaseType),  attrs);
            var des = new XmlSerializer(typeof (BaseType), attrOverrides);

            using (var memeStream= new MemoryStream())
            {
                serializer.Serialize(memeStream, specialType);
                memeStream.Flush();

                memeStream.Seek(0, SeekOrigin.Begin);
                var instance = des.Deserialize(memeStream); 
            }

}

[XmlInclude(typeof(SpecialType))]
[XmlType("baseType")]
public class BaseType
{
      public long Id { get; set; }
}

[XmlRoot("special")]
public class SpecialType : BaseType
{
        public string Name { get; set; }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM