XmlSerializer反序列化类层次结构

时间:2013-01-29 14:57:30

标签: c# xml serialization

我在.NET中遇到了XmlSerializer的一些问题。

这里我有一个我刚刚建立的小例子。 (也可以@ 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; }
    }
}

在代码的第24行,我得到一个InvalidOperationException,声明“{”< special xmlns =''> wurde nicht erwartet。“}”[是的,这是德语]

我发现所有帖子都说明了,在反序列化的基类型上添加XmlIncludeAttribute后,这应该有效。我忘记了吗?

此致 的MacX

1 个答案:

答案 0 :(得分:4)

问题是你的Serializer使用根元素序列化SpecialType:

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

但是你尝试使用var des = new XmlSerializer(typeof (BaseType));反序列化它,它知道这两种类型,但它不知道如何处理xml中的root元素。

如果您希望这样做,您还需要将基本类型的根元素设置为序列化为special。换句话说,您需要这样做:

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

这样,反序列化器知道如何处理special作为根元素。

我认为还有其他简单的替代品可以让这项工作开箱即用。

更新

这是使用XmlAttributeOverrides类的另一种选择。

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