XmlSerializer — как установить значение по умолчанию при десериализации перечисления?

У меня есть класс, который выглядит так (сильно упрощенный):

public class Foo
{
    public enum Value
    {
        ValueOne,
        ValueTwo
    }

    [XmlAttribute]
    public Value Bar { get; set; }
}

Я получаю файл XML из внешнего источника. В их документации указано, что элемент Foo всегда будет иметь только «ValueOne» или «ValueTwo» в атрибуте Bar (они не предоставляют XSD).

Итак, я десериализую это так:

 var serializer = new XmlSerializer(typeof(Foo));
 var xml = "<Foo Bar=\"ValueTwo\" />";
 var reader = new StringReader(xml);

 var foo = (Foo)serializer.Deserialize(reader);

... и все работает.

Однако прошлой ночью мне прислали XML-код, похожий на этот, и моя десериализация не удалась (как и должно быть):<Foo Bar="" />

Есть ли хороший способ защитить код вокруг этого? В идеале я хотел бы сказать что-то вроде «по умолчанию ValueOne, если что-то пойдет не так». Я не хочу выбрасывать весь файл XML, потому что один атрибут был искажен.


person NeilD    schedule 31.10.2012    source источник
comment
stackoverflow.com/a/1266758/485076   -  person sll    schedule 31.10.2012
comment
Вы можете сначала попробовать создать объект XML из входной строки, затем перебрать узлы и заменить все пустые значения на ValueOne.   -  person FLClover    schedule 31.10.2012


Ответы (2)


вы можете установить перечисление следующим образом, так что это установит значение перечисления в Unknown = 0, что-то вроде значения по умолчанию

public enum Foo
{
   [XmlEnum(Name = "")]
   Unknown =0,
   [XmlEnum(Name = "Single")]
   One,
   [XmlEnum(Name = "Double")]
   Two   
}

более подробная проверка: Класс XmlEnumAttribute

person Pranay Rana    schedule 31.10.2012
comment
Хм... Это достойный вариант, но он требует, чтобы я заранее знал все потенциальные плохие значения. Я хотел бы что-то, что справится, если они отправят , или ValueThree, или SomethingTotallyRandom. - person NeilD; 31.10.2012

Сбить XmlSerializer.. Используйте LINQ2XML для этой простой задачи

XElement doc=XElement.Load("yourStreamXML"); 

List<Foo> yourList=doc.Descendants("Foo")
.Select(x=>
new Foo
{
    Bar=(Enum.GetNames(typeof(Value)).Contains(x.Attribute("Bar").Value))?((this.Value)x.Attribute("Bar")):(this.Value.ValueOne);
}
).ToList<Foo>();

Так что я в основном делаю это

if(Enum.GetNames(typeof(Value)).Contains(x.Attribute("Bar").Value))
//if the xml bar value is a valid enum
    Bar=(this.Value)x.Attribute("Bar");
else//xml bar value is not a valid enum..so use the default enum i.eValueOne
    Bar=this.Value.ValueOne;
person Anirudha    schedule 31.10.2012
comment
Я думаю, что класс Foo намного больше, и автор пытается избежать ручной десериализации. - person Dmitry Dovgopoly; 31.10.2012
comment
Да, реальная структура XML и классов просто ОГРОМНА! Было бы очень сложно реорганизовать все для работы с Linq2Xml. - person NeilD; 31.10.2012