2

.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 行目で、"{"<special xmlns=''> wurde nicht erwartet."}" [はい、ドイツ語です] という InvalidOperationException を取得します。

私が見つけたすべての投稿は、逆シリアル化されている基本型に XmlIncludeAttribute を追加した後、これが機能するはずです。私はsthを忘れましたか?

よろしく、 MacX

4

1 に答える 1

4

問題は、Serializerがルート要素を使用してSpecialTypeを次のようにシリアル化していることです。

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

しかし、それを使用して逆シリアル化しようとすると 、両方のタイプを認識していますが、xml内var des = new XmlSerializer(typeof (BaseType));の要素を処理する方法がわかりません。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; }
}
于 2013-01-29T15:34:39.433 に答える