当两个类具有相同名称的属性时,.NET XmlSerializer错误

时间:2011-04-14 04:39:54

标签: .net xmlserializer

让你的火焰火把准备好的人!互联网上有人建议.NET框架中存在错误! : - )

考虑这个人为的模型:

public class Barn
{
    public Horse Horse { get; set; }
    public Motorcycle Motorcycle { get; set; }
}

public class Horse
{
    public Horse()
    {
        Rider = "Jim Craig";
    }

    [XmlElement(IsNullable = true, Namespace = "abc")]
    public string Rider { get; set; }
}

public class Motorcycle
{
    public Motorcycle()
    {
        Rider = "Ghost";
    }

    [XmlElement(IsNullable = false, Namespace = "abc")]
    public string Rider { get; set; }
}

请注意两个共享相同名称和命名空间的Rider属性,但这些属性不相关。一个是XML可空,另一个不是。

以下是XML序列化然后反序列化空马骑手的一些代码:

// Create a Barn, with a Horse, with a null Rider
Barn barnBefore = new Barn();
barnBefore.Horse = new Horse();
barnBefore.Horse.Rider = null;

// Serialize and then deserialize the Barn
XmlSerializer serializer = new XmlSerializer(typeof(Barn));
MemoryStream stream = new MemoryStream();
serializer.Serialize(stream, barnBefore);
stream.Seek(0, SeekOrigin.Begin);
Barn barnAfter = (Barn)serializer.Deserialize(stream);

// Is the Horse's Rider still null?
Console.WriteLine(barnAfter.Horse.Rider == null ? "null" : "not null");

Horse的{​​{1}}属性有Rider,因此应通过序列化维护其空值。运行上面的代码,输出确实是 null 。到目前为止一切都很好。

现在,这是有趣的部分:交换IsNullable = true类中HorseMotorcycle属性的顺序,以便Barn成为第一。

再次运行,现在输出不为空。怎么了?!

我在VS 2008和2010上进行了测试。

为了获得更多乐趣,请尝试将两个Motorcycle属性设置为不同的类型,例如一个Rider,另一个string。那个真的搞砸了int

我对如何解决这个问题不感兴趣。那是微不足道的。我的问题是:这是一个错误,还是我误解了什么?

1 个答案:

答案 0 :(得分:3)

嗯,在第一种情况下,写入的XML看起来有点像这样:

<Barn>
  <Horse>
    <Rider xsi:nil="true" xmlns="abc" />
  </Horse>
</Barn>

然而在第二种情况下,XML看起来像这样:

<Barn>
  <Horse />
</Barn>

所以在第二种情况下,反序列化过程中发生的事情基本上就是:

Barn barn = new Barn();
barn.Hose = new Horse();

因为我们在构造函数中默认设置Rider,所以它被留作“Jim Craig”。

有趣的是,只需更改Barn中元素的顺序即可撤消行为。要尝试发现更多信息,我们可以使用ILSpySgen.exe进行一些挖掘 - 只需对我们的程序集运行sgen,然后查看生成的程序集。

我们发现在第一种情况下,两者 Write2_HorseWrite3_Motorcycle方法中生成的代码都有一行如下所示:

base.WriteNullableStringLiteral("Rider", "abc", o.Rider);

然而在第二种情况下它看起来像这样:

base.WriteElementString("Rider", "abc", o.Rider);

我看不出为什么改变这样的元素的顺序应该以这种方式改变HorseMotorcycle元素的序列化行为的任何理由,所以简而言之这看起来像对我来说就像XML序列化程序集生成器中的一个错误。

您应该向Microsoft报告: - )