Поэтому я недавно обновил проект с .NET 3.5 до .NET 4.6, и моя сериализация XML перестала работать. Я сузил это до одной структуры, которая, я согласен, выглядит странно.
[XmlElement("price1", typeof(PriceBonusData))]
[XmlElement("price2", typeof(PriceBonusData))]
public List<PriceBonusData> PriceBonusDataList;
Ошибка говорит о том, что мне нужно добавить атрибут XmlChoiceIdentifier
в это поле, но как бы я его ни добавил, он все равно не работает. То, что кажется странным, это то, что он работал на .NET 3.5, так почему внезапная потребность в новом атрибуте?
Изменение: вот моя попытка использовать XmlChoiceIdentifier. Я видел похожие решения как в документации, так и в SO, но, похоже, у меня не работает.
[XmlElement(IsNullable = false)]
[XmlIgnore]
public ItemChoiceType[] ItemTypeArray = (ItemChoiceType[])Enum.GetValues(typeof(ItemChoiceType));
[XmlChoiceIdentifier("ItemTypeArray")]
[XmlElement("price1", typeof(PriceBonusData))]
[XmlElement("price2", typeof(PriceBonusData))]
public List<PriceBonusData> PriceBonusDataList;
[XmlType(IncludeInSchema = false)]
public enum ItemChoiceType
{
[XmlEnum("price1")]
price1,
[XmlEnum("price2")]
price2
}
Edit2: я запустил некоторые дополнительные тесты для пустого проекта с версией .NET 3.5, поэтому я решил поделиться тем, как это происходит, когда это работает.
Эта структура сериализуется с использованием последнего XmlElement (в данном случае "price2").
Во время десериализации оба элемента действительны. Я вручную изменил XML файл, чтобы он содержал "price1" и "price2", и он правильно десериализует их.
Если вы только пытаетесь десериализовать, то, возможно, это подойдет вам:
public class Foo
{
// the "real" list that takes <price1> elements
[XmlElement("price1", typeof(PriceBonusData))]
public List<PriceBonusData> PriceBonusDataList {get;} = new List<PriceBonusData>();
// spoof a second list that handles <price2> elements (actually: the same list)
[XmlElement("price2", typeof(PriceBonusData))]
public List<PriceBonusData> PriceBonusDataList2 => PriceBonusDataList;
// this disables serialization of PriceBonusDataList2 so we don't double up
public bool ShouldSerializePriceBonusDataList2() => false;
}
Недостатком является то, что если вы его сериализуете, все станет <price1>
, независимо от того, началось ли это как <price1>
или <price2>
... но... я не вижу никакого способа обойти это, так как нет нигде хранить то, что было изначально.
PriceBonusData
в нем?<price1>
,<price2>
? обе?