问题
This is a note to my future self, and for the benefit of others. The described behavoir is NOT obvious...
I've got this bit of C#:
public enum Choices
{
One,
Two,
Three,
}
public class Element
{
List<Choices> _allowedChoices;
[XmlAttribute]
public List<Choices> AllowedChoices
{
get {return _allowedChoices ?? ( _allowedChoices = new List<Choices>() );}
set { _allowedChoices = value; }
}
}
[Test]
public void testing_empty_enum_list_serialization()
{
var ser = new XmlSerializer(typeof (Element));
using (var sw = new StringWriter())
{
ser.Serialize(sw, new Element
{
AllowedChoices = {},
});
var text = sw.ToString();
Console.WriteLine(text);
using (var sr = new StringReader(text))
{
var deserialized = (Element) ser.Deserialize(sr);
}
}
}
If I use the XmlSerializer to serialize this to xml I get:
( Note the empty AllowedChoices attribute at the end )
<?xml version="1.0" encoding="utf-16"?>
<Element xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" AllowedChoices="" />
If I then use the XmlSerializer to deserialize this xml I something like:
System.InvalidOperationException : There is an error in XML document (2, 109).
----> System.InvalidOperationException : Instance validation error: '' is not a valid value for Choices.
This is an empty list of enums that serializes without error, Y U NO deserialize!?
回答1:
I've found these related questions, which fail for expected reasons, namely that an enum does not have a null default value, which is a clue...
deserializing enums
XmlSerializer enumeration deserialization failing on (non existent) whitespace
And this is the solution:
If the implementation of AllowedChoices is an auto-property and is not initialized in the constructor (i.e. it's null when deserialization gets to that property) it works as expected, and does not bomb on deserialization.
I have full control over the source, so I'm going to be pragmatic and add an None value to my Choices enum with a [XmlEnum("")] attribute, and treat the list as empty if that's the only value in the list instead of not doing auto-initialization of the list.
See http://tech.pro/blog/1370/why-collections-should-never-be-null for why I want that.
Bonus tip:
If you want to create an empty-string of an enum alias do it like this:
public enum Choices
{
[XmlEnum("default")]
Default = 0,
[XmlEnum("")]
DefaultAlias = Default,
}
来源:https://stackoverflow.com/questions/21878110/c-sharp-xmlserializer-fails-on-deserialization-of-an-empty-enum-list-if-its-in