XmlSerializer序列化属性中的一个空整数列表

时间:2019-05-29 08:54:15

标签: c# .net xml .net-core xml-deserialization

考虑这样的元素:

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="XMLSchema1" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="Foo">
    <xs:complexType>
      <xs:attribute name="MyList">
        <xs:simpleType>
          <xs:list itemType="xs:int" />
        </xs:simpleType>
      </xs:attribute>
    </xs:complexType>
  </xs:element>
</xs:schema>

例如:

<Foo MyList='1 2 3' />

这对应于C#类:

[Serializable]
public class Foo
{
  [XmlAttribute]
  public int[] MyList { get; set; }
}

(基本上)就是xsd.exe /classes生成的。

序列化和反序列化非常有效,除了反序列化一个空列表之外:

var ser = new XmlSerializer(typeof(Foo));
ser.Deserialize(new StringReader("<Foo MyList='' />"));

AFAIK,这是完全合法的XML,但是XmlSerializer将抛出InvalidOperationException

System.InvalidOperationException: There is an error in XML document (1, 6). ---> System.FormatException: Input string was not in a correct format.
   at System.Number.StringToNumber(String str, NumberStyles options, NumberBuffer& number, NumberFormatInfo info, Boolean parseDecimal)
   at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderFoo.Read2_Foo(Boolean isNullable, Boolean checkType)
   at Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReaderFoo.Read3_Foo()
   --- End of inner exception stack trace ---
   at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader xmlReader, String encodingStyle, XmlDeserializationEvents events)
   at System.Xml.Serialization.XmlSerializer.Deserialize(TextReader textReader)
   at Blah.Program.Main(String[] args) in Program.cs:line 17

(此异常来自.NET 4.7.2; .NET Core 2.2引发具有几乎相同的堆栈跟踪的相同异常。)该异常是有道理的,因为""不是整数。

这里有similar question,但这是关于枚举的,我不知道如何在int s中使用答案。

如何在不实现IXmlSerializable的情况下反序列化一个空列表(这需要大量额外的编码)?

1 个答案:

答案 0 :(得分:1)

我不确定您可以使用序列化程序属性来完成这项工作,并且由于它是一个属性,因此您无法添加复杂类型来帮助隐藏问题。您可以使用代理属性来将输入作为字符串来处理,以解决此问题,虽然它不是很漂亮,但却可以避免使用全面的IXmlSerializable实现。

[Serializable]
public class Foo
{
    [XmlIgnore]
    public int[] MyList { get; set; }

    [XmlAttribute(AttributeName = "MyList")]
    public string MyListProxy
    {
        get
        {
            if (MyList == null) return String.Empty;
            return String.Join(" ", MyList);
        }
        set
        {
            MyList = String.IsNullOrWhiteSpace(value) ? new int[0] : value
                .Split(' ')
                .Select(a => int.Parse(a))
                .ToArray();
        }
    }
}