Wojtek Pojda
Wojtek Pojda

Reputation: 134

XmlSerializer errors after updating from .NET 3.5 to .NET 4.6

So I recently updated a project from .NET 3.5 to .NET 4.6 and my XML serialization stopped working. I narrowed it down to a single structure that, I agree, looks weird.

[XmlElement("price1", typeof(PriceBonusData))]
[XmlElement("price2", typeof(PriceBonusData))]
public List<PriceBonusData> PriceBonusDataList;

The error says that I need to add XmlChoiceIdentifier attribute to this field, but no matter how I add it, it still doesn't work. What seems strange is that it did work on .NET 3.5, so why the sudden need for new attribute?

Edit: here is my attempt to use XmlChoiceIdentifier. I saw similar solutions both in documentation and on SO, but it doesn't seem to work for me.

[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: I run some further tests on an empty project with .NET 3.5 version so I figured I could share how this behaves when this works.

This structure is serialized using last XmlElement (in this case "price2").

During deserialization both elements are valid. I manually changed XML file so it contains both "price1" and "price2" and it deserializes them correctly.

Upvotes: 2

Views: 240

Answers (1)

Marc Gravell
Marc Gravell

Reputation: 1063774

If you're only trying to deserialize, then maybe this will work for you:

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;
}

The downside is that if you serialize it, everything will become <price1>, regardless of whether it started as a <price1> or <price2>... but... I can't see any way around that, since there's nowhere to store what it was originally.

Upvotes: 1

Related Questions