XML序列化和空集合

时间:2020-03-05 18:55:07  来源:igfitidea点击:

我有一个属性定义为:

[XmlArray("delete", IsNullable = true)]
[XmlArrayItem("contact", typeof(ContactEvent)),
 XmlArrayItem("sms", typeof(SmsEvent))]
public List<Event> Delete { get; set; }

如果List <> Delete没有项目

<delete />

被发射。如果List <> Delete设置为null

<delete xsi:nil="true" />

被发射。如果集合中没有项目,有没有一种方法可以使用属性来使delete元素不被发出?

Greg Perfect,谢谢,我什至没有读过IsNullable文档,只是假设它表明不需要使用它。

罗伯·库珀(Rob Cooper)我试图避免ISerializable,但格雷格斯(Gregs)的建议行之有效。我确实遇到了我们在(1)中概述的问题,如果集合的长度为零,我只是通过返回null来破坏了一堆代码。为了解决这个问题,我创建了一个EventsBuilder类(我正在序列化的类称为事件),该类管理Events类的基础对象的所有生存期/创建时间,这些事件/事件将我们的Events类吐出进行序列化。

解决方案

回答

我们始终可以实现IXmlSerializer并手动执行序列化。

有关示例,请参见http://www.codeproject.com/KB/cs/IXmlSerializable.aspx。

回答

如果设置IsNullable = false或者将其删除(默认情况下为false),则不会发出"删除"元素。仅当collection等于null时,此方法才有效。

我的猜测是,在.NET方面的"可空性"和与XML中可空元素相关的那些之间存在混淆,这些元素由xml:nil属性标记。 XmlArrayAttribute.IsNullable属性控制后者。

回答

首先,我要问自己"什么是序列化?"。

XmlSerializer完全按照预期的方式运行,将对象的当前状态持久保存为XML。现在,我不确定为什么当前行为对我们而言不是"正确"的,因为如果我们已经初始化了列表,那么它将被初始化。

我认为我们在这里有三个选择:

  • 如果该集合包含0个项目,则将代码添加到Getter以返回null。这可能会弄乱我们拥有的其他代码。
  • 实现IXmlSerializable接口并自己完成所有工作。
  • 如果这是一个常见的过程,那么我们可能想看一下我的问题" XML序列化和继承的类型"-是的,我知道它涉及另一个问题,但是它向我们展示了如何创建一个通用的中介序列化类,该类可以"固定"以允许系列化过程被封装。我们可以创建一个类似的类来处理覆盖空/零项目集合的默认过程。

我希望这有帮助。

回答

我遇到了同样的问题,如果字段为空或者为0,我不希望输出元素。
输出的XML不能使用xsi:null =" true"(根据设计)。

我在某处读到,如果我们包含bool类型的属性,该属性的名称与我们要控制的字段的名称相同,但添加了" Specified",则XMLSerializer将检查此属性的返回值以确定相应的字段是否为包括。

要在不实现IXMLSerializer的情况下实现此目的,请执行以下操作:

public List<Event> Delete { get; set; }
[XMLIgnore]
public bool DeleteSpecified
{
 get
 {
   bool isRendered = false;
   if (Delete != null)
   {
     isRendered = (Delete.Count > 0);
   } 

   return isRendered;
 }
 set
 {
 }
}