如何在c#中将null数组反序列化为null?

Aen*_*dhe 11 c# xml arrays serialization nullable

这是我的班级:

public class Command
{
   [XmlArray(IsNullable = true)]
   public List<Parameter> To { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

当我序列化这个类的对象时:

var s = new XmlSerializer(typeof(Command));
s.Serialize(Console.Out, new Command());
Run Code Online (Sandbox Code Playgroud)

它按预期打印(省略xml标头和默认MS名称空间):

<Command><To xsi:nil="true" /></Command>
Run Code Online (Sandbox Code Playgroud)

当我拿这个xml并试图反序列化它时我被卡住了,因为它总是打印"Not null":

var t = s.Deserialize(...);
if (t.To == null)
    Console.WriteLine("Null");
else
    Console.WriteLine("Not null");
Run Code Online (Sandbox Code Playgroud)

如果强制反序列化器使我的列表为null,如果它在xml中为null?

Jus*_*tin 5

如果您使用数组而不是列表,它会按预期工作

public class Command
{
    [XmlArray(IsNullable = true)]
    public Parameter[] To { get; set; }
}
Run Code Online (Sandbox Code Playgroud)


Han*_*ant 2

呃,烦人不是吗。您可以通过使用 /keep 和 /debug 选项在程序集上运行 sgen.exe 来查看它的执行情况,以便您可以调试反序列化代码。它看起来大致是这样的:

\n\n
global::Command o;\no = new global::Command();\nif ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();\nglobal::System.Collections.Generic.List<global::Parameter> a_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;\n// code elided\n//...\nwhile (Reader.NodeType != System.Xml.XmlNodeType.EndElement && Reader.NodeType != System.Xml.XmlNodeType.None) {\n  if (Reader.NodeType == System.Xml.XmlNodeType.Element) {\n    if (((object)Reader.LocalName == (object)id4_To && (object)Reader.NamespaceURI == (object)id2_Item)) {\n      if (!ReadNull()) {\n        if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();\n        global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;\n        // code elided\n        //...\n      }\n      else {\n        // Problem here:\n        if ((object)(o.@To) == null) o.@To = new global::System.Collections.Generic.List<global::Parameter>();\n        global::System.Collections.Generic.List<global::Parameter> a_0_0 = (global::System.Collections.Generic.List<global::Parameter>)o.@To;\n      }\n    }\n  }\n  Reader.MoveToContent();\n  CheckReaderCount(ref whileIterations1, ref readerCount1);\n}\nReadEndElement();\nreturn o;\n
Run Code Online (Sandbox Code Playgroud)\n\n

不少于 3 个地方确保 @To 属性不为 null。第一个是有一定道理的,当结构不存在时很难反序列化数据。第二个再次进行空测试,这是唯一真正好的测试。第三个问题是,ReadNull() 返回 true 但它仍然创建一个非 null 属性值。

\n\n

如果您想区分空和空,那么您没有好的解决方案,只能手动编辑此代码。只有当你真的绝望并且班级 100% 稳定时才这样做。好吧,别这样做。Jo\xc3\xa3o 的解决方案是唯一好的解决方案。

\n