XmlSerializer: как десериализовать значение перечисления, которое больше не существует

Я использую XMLSerializer для сохранения этого класса в файл. У класса есть строка и перечисление, как показано ниже:

public class IOPoint
{
     string Name {get; set;}
     TypeEnum {get; set;}
}


public enum TypeEnum
{
    Temperature,
    Pressure,
    Humidity,
}

Когда сериализуется, это выглядит так.

<IOPoint>
  <Name>Relative Humidity</Name>
  <TypeEnum>Humidity</TypeEnum>
</IOPoint>

Я сериализовал и десериализовал этот объект без проблем для нескольких версий. Я больше не хочу поддерживать влажность, поэтому я удалил ее из перечисления. Однако это вызывает исключение при десериализации из XML, поскольку значение в поле TypeEnum, Humidity, не является допустимым значением для TypeEnum. Это имеет смысл, но как справиться с этим?

То, что я хотел бы сделать, это просто игнорировать эту ошибку. И оставьте значение как ноль. Я пытался реализовать класс OnUnknownElement XmlDeserilizationEvent. К сожалению, это не ловит эту ошибку.

Любые идеи о том, как отловить и игнорировать эту ошибку (я могу исправить после завершения десериализации).

Митч

 avenmore17 янв. 2018 г., 07:21
Если бы вы нашли решение, которое я хотел бы узнать. У меня есть проблема, связанная с тем, что на стороне сервера есть новое значение флага enum, о котором клиент не знает, поэтому очень хочу найти способ управления сериализацией только одного этого поля. В следующий раз я просто буду использовать int, но пока ... обратная совместимость.

Ответы на вопрос(4)

как ваша библиотека уже используется. Почему вы не оставляете участника на месте, а пометьте его знаком[Obsolete] атрибут для предотвращения использования в будущем? УказаниеObsoleteAttribute(string,bool)торой параметр конструктора @ какtrue вызовет ошибку во время компиляции, если к отмеченному элементу будет получен доступ.

public enum TypeEnum
{
    Temperature,
    Pressure,

    [Obsolete("It's always sunny in Philadelphia", true)]
    Humidity,
}

Чтобы обойти ошибку при проверке десериализованных значений, вы можете сравнить с базовым значением:typeEnum == (TypeEnum)2.

ментов от сериализации xml, анализируя только один этот элемент вручную:

public class IOPoint
{
 public string Name {get; set;}

 [XmlIgnore]
 public TypeEnum TypeEnum {get; set;}

 [XmlElement("TypeEnum")]
 public string LegacyTypeEnum 
 {
  get { return this.TypeEnum.ToString(); }
  set 
  { 
   try
   {
    this.TypeEnum = (TypeEnum)Enum.Parse(typeof(TypeEnum),value);
   }
   catch(ArgumentException)
   {
    // Handle "Humidity"
   }
   catch(OverflowException)
   {
   }
  }
 }
}

Per комментарии, кажется, некоторая путаница; Вот пример работы как проект Visual Studio 2010. Этот подход представляет собой простой способ синтаксического анализа только одного свойства объекта (все еще используя XmlSerializer для анализа XML).

 user42343031 мая 2012 г., 14:05
Я включил скомпилированный пример, чтобы продемонстрировать, как он работает, и как он работает.
 Mitch23 мая 2012 г., 15:50
Сериализация значения перечисления в виде строки вместо перечисления будет хорошей идеей, если у меня еще не было файлов XML, которые мне нужно прочитать. Эти существующие файлы имеют элемент <TypeEnum \>, и мне все еще нужно прочитать значение поля TypeEnum и действовать соответственно. Идеальным решением было бы поймать исключение при попытке десериализации значения влажности. Но ни один из обработчиков исключений, которые вы добавили в десериализатор, не уловит эту ошибку.

IXmlSerializable, где вы можете использовать что-то вроде TryParse для перечисления.

Но я согласен с другими авторами, использующими атрибут "Устаревший".

 Mitch23 мая 2012 г., 15:56
Если я не могу найти другого обходного пути, пользовательская сериализация с использованием IXMLSerializable может быть единственным решением. Пока я в этом, я бы также добавил поле Версия, которое я мог бы использовать для направления десериализации. Мы делаем нечто подобное при использовании ISerializable. В реальном классе около 15 полей. Интересно, смогу ли я просто написать код десериализатора для одного поля?

Вы можете пометить участника как устаревшего

public enum TypeEnum
{
    Temperature,
    Pressure,
    [Obsolete]
    Humidity
}
 Mitch22 мая 2012 г., 23:49
Причина, по которой я не могу использовать атрибут [Устаревший], заключается в том, что в нашем коде принято перебирать значения перечисления. Таким образом, даже если «Влажность» помечена как устаревшая, она все равно будет обнаружена в наших циклах foreach. (Разве есть способ переопределить перечислитель?)
 user336273516 сент. 2016 г., 21:46
Можете ли вы сделать переменную нулевой везде, где вы ее используете? например, TypeEnum? val = ноль;

Ваш ответ на вопрос