我正在我的一个类中实现IXMLSerializable。它包含一些可以为空的数字属性(int?double?etc ..)
通过IXMLSerializable序列化/序列化这些的正确方法是什么?这就是我现在正在做的,哪个有效,但显然不是正确的做法。
void IXmlSerializable.WriteXml(XmlWriter writer)
{
...
if (this._PropName == null)
{
writer.WriteElementString("PropName", "NULL");
}
else
{
writer.WriteElementString("PropName", this._PropName.ToString());
}
...
}
void IXmlSerializable.ReadXml(XmlReader reader)
{
string tempStr;
...
reader.ReadStartElement("PropName");
if (tempStr != "NULL")
{
this._PropName = double.Parse(tempStr);
}
else
{
this._PropName = null;
}
...
}
更新 有人问我为什么要实施 IXmlSerializable 。我正在开发一个建筑设计程序,我需要一个代表Floors集合的类。每个楼层都具有 Floor.Area 区域, Floor.Height 等属性。但是,楼层的高程由总和定义在它下面的地板高度。因此,只要 Floor.Height 属性发生更改或 FloorCollection 被修改, Floors 的高程就会被重新调整。
我需要序列化的 FloorCollection 类继承自BindingList。如果我尝试直接序列化这个类,它将序列化楼层集合,但不会序列化类中的任何属性或字段。查看我的previous post on this。
现在我正在尝试添加限制集合中建筑物楼层的最大高度,最大顶部高程和最小底部高程的功能。所以我使用可以为空的双精度来表示这些限制,其中空值意味着不受限制。高程属性可以是正数,负数或零。因此需要有一个替代状态null,它标识何时没有限制。
现在我认为总体上可能更容易只有一个单独的布尔值来标识是否存在高程/高度限制,然后是一个常规的双属性,用于标识启用时的限制条件。
答案 0 :(得分:3)
如果元素为null,则省略该元素。
修改的
考虑如果您制作了添加属性的新版本会发生什么。如果您随后反序列化了旧版本的副本,则包含新属性的新元素将会丢失,因此您将正确地保留未初始化的属性,为null。这是相同的逻辑,扩展到涵盖现在时。
修改的
有关如何告诉XmlSerializer在不编写自定义序列化程序的情况下省略null属性的信息,请查看this。另外,鉴于背景信息,虽然我仍然喜欢遗漏xsi:nil,但我现在认为后者是可接受的解决方案。
答案 1 :(得分:3)
您希望始终为属性编写XML,但如果属性值为null,则希望包含xsi:nil =“true”属性。
void IXmlSerializable.WriteXml(XmlWriter writer)
{
...
if (this._PropName == null)
{
writer.WriteStartElement("PropName");
writer.WriteAttributeString("xsi", "nil", "http://www.w3.org/2001/XMLSchema-instance", "true");
writer.WriteEndElement();
}
else
{
writer.WriteElementString("PropName", this._PropName.ToString());
}
...
}
您可能还想编写xsi:type =“xsd:数据类型”属性,其中xsd是http://www.w3.org/2001/XMLSchema命名空间。这将允许您在反序列化期间重新读取数据类型,以了解是否(以及如何)转换该值。
答案 2 :(得分:1)
你可以写一个null:
writer.WriteElementString("Test", null);
它只会产生像<Test/>
或者对null值更具体一点,您可以使用xsi:nil属性:
const string xsiNs = "http://www.w3.org/2001/XMLSchema-instance";
using (XmlWriter writer = XmlWriter.Create(Console.Out))
{
writer.WriteStartElement("Test");
writer.WriteAttributeString("xsi", "nil", xsiNs, "true");
writer.WriteEndElement();
}
将导致<Test xsi:nil="true"/>
答案 3 :(得分:0)
void IXmlSerializable.WriteXml(XmlWriter writer)
{
if (this._Foo == null)
{
writer.WriteStartElement("Foo");
writer.WriteEndElement("Foo");
}
else
{
writer.WriteElementString("Foo", this._Foo.ToString());
}
}