XML序列化和空集合

3

我有一个定义为:

[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" />

如果集合中没有项目,是否有使用属性的方法使删除元素不被发出?

Greg - 太棒了,谢谢,我甚至没有阅读IsNullable文档,只是假设它是不需要的信号。

Rob Cooper - 我试图避免使用ISerializable,但Greg的建议有效。我确实遇到了你在(1)中概述的问题,如果集合长度为零,我通过返回null破坏了一堆代码。为了解决这个问题,我创建了一个EventsBuilder类(我正在序列化的类称为Events),它管理Events类的所有生命周期/创建,并为序列化提供Events类。


我在http://www.codepoets.co.nz/2009/03/03/handling-null-strings-using-xmlserializerdeserialize/上详细介绍了这个问题。会尝试@theahuramazda的建议并更新。 - Nic Strong
4个回答

19
我遇到了同样的问题,如果字段为空或为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
 {
 }
}

1
http://geekswithblogs.net/shahed/archive/2007/07/11/113881.aspx 是一篇解释这种机制的文章。 - MattDavey
经进一步阅读,发现这种方法仅适用于值类型。 - MattDavey
3
对于非值类型,如上面所示的列表,这似乎可以正常工作。为了简洁起见,您可以将代码缩短为以下内容: get { return Delete != null && Delete.Count > 0; } - ThisIsTheDave

5
如果您将IsNullable设置为false或仅删除它(默认为false),则不会发出“delete”元素。这仅在集合等于null时有效。
我猜测存在.NET中的“可空性”和与XML中可空元素相关的混淆--那些由xml:nil属性标记的元素。XmlArrayAttribute.IsNullable属性控制后者。

3
这个回答没有解决问题吗?“是否有一种方法可以使用属性,如果集合中没有项目,则不发出删除元素?”这基本上就是问者现在的情况? - Rob Cooper

1

首先,我想说问问自己“什么是序列化?”。

XmlSerializer正在执行它应该执行的操作,将对象的当前状态持久化为XML。现在,我不确定为什么当前行为对您来说不是“正确”的,因为如果您已经初始化了List,那么它就已经被初始化了。

我认为你有三个选择:

  1. 在Getter中添加代码,如果集合中没有任何项,则返回null。但这可能会破坏您拥有的其他代码。
  2. 实现IXmlSerializable接口并自己完成所有工作。
  3. 如果这是一个常见的过程,那么您可能需要查看我的问题“XML Serialization and Inherited Types”-是的,我知道它涉及另一个问题,但它向您展示了如何创建一个通用的中介序列化类,然后可以“附加”以允许封装序列化过程。您可以创建一个类似的类来处理覆盖空/零项集合的默认过程。

希望这可以帮助到您。


0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接