这是我的班级:
public class Command
{
[XmlArray(IsNullable = true)]
public List<Parameter> To { get; set; }
}
当我序列化这个类的对象时:
var s = new XmlSerializer(typeof(Command));
s.Serialize(Console.Out, new Command());
按预期打印(省略xml标头和默认MS名称空间):
<Command><To xsi:nil="true" /></Command>
当我拿这个xml并试图反序列化时,我被卡住了,因为它总是打印“Not null”:
var t = s.Deserialize(...);
if (t.To == null)
Console.WriteLine("Null");
else
Console.WriteLine("Not null");
如果强制反序列化器使我的列表为空,如果它在xml中为null?
答案 0 :(得分:3)
如果使用数组而不是列表,则按预期工作
public class Command
{
[XmlArray(IsNullable = true)]
public Parameter[] To { get; set; }
}
答案 1 :(得分:2)
global::Command o;
o = new global::Command();
if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();
global::System.Collections.Generic.List<global::Parameter> a_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;
// code elided
//...
while (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.NodeType != System.Xml.XmlNodeType.None) {
if (Reader.NodeType == System.Xml.XmlNodeType.Element) {
if (((object)Reader.LocalName == (object)id4_To && (object)Reader.NamespaceURI == (object)id2_Item)) {
if (!ReadNull()) {
if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();
global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;
// code elided
//...
}
else {
// Problem here:
if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();
global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;
}
}
}
Reader.MoveToContent();
CheckReaderCount(ref whileIterations1, ref readerCount1);
}
ReadEndElement();
return o;
不少于3个地方确保@To属性不为null。第一个是有点可辩护的,当结构不存在时难以反序列化数据。第二个再次进行空测试 ,这是唯一真正好的测试。第三个是问题,ReadNull()返回true但仍然创建一个非null属性值。
如果你想区分空和null,那么你没有好的解决方案,但手动编辑这段代码。如果你真的很绝望并且该课程100%稳定,那么这只 。好吧,不要这样做。 João的解决方案是唯一的好解决方案。
答案 2 :(得分:0)
我同意@Oliver的评论,但是你可以像这样解决它,如果你绝对需要它来返回null。而不是使用自动属性,创建自己的支持字段。
List<Parameter> _to;
public List<Parameter> To
{
get
{
if (_to != null && _to.Count == 0) return null;
return _to;
}
set { _to = value; }
}
答案 3 :(得分:0)
如果你确实需要将一个集合反序列化为null
,当没有提供任何值时,你可以通过不提供set
访问器来实现,如下所示:
public class Command
{
private List<Parameter> to;
public List<Parameter> To { get { return this.to; } }
}
答案 4 :(得分:0)
对于需要它的人,可以将其类型定义为具有原始元素名称的数组,然后将其包装,这将为您提供可为空的列表。
[XmlArray(ElementName = nameof(Metadata), IsNullable = true)]
public string[] MetadataArray { get; set; }
[XmlIgnore]
public List<string> Metadata
{
get => this.MetadataArray?.ToList();
set => this.MetadataArray = value?.ToArray();
}