考虑这样的元素:
<?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
的情况下反序列化一个空列表(这需要大量额外的编码)?
答案 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();
}
}
}