Устаревший атрибут приводит к тому, что свойство игнорируется XmlSerialization - PullRequest
50 голосов
/ 01 декабря 2008

Я выполняю рефакторинг некоторых объектов, которые сериализованы в XML, но необходимо сохранить несколько свойств для обратной совместимости. У меня есть метод, который преобразует старый объект в новый для меня и обнуляет устаревшее свойство. Я хочу использовать атрибут Obsolete, чтобы другие разработчики не использовали это свойство, но оно вызывает игнорирование свойства XmlSerializer.

Аналогичный код:

[Serializable]
public class MySerializableObject
{
    private MyObject _oldObject;
    private MyObject _anotherOldObject;

    private MyObject _newBetterObject;

    [Obsolete("Use new properties in NewBetterObject to prevent duplication")]
    public MyObject OldObject
    {
      get { return _oldObject; }
      set { _oldObject = value; }
    }

    [Obsolete("Use new properties in NewBetterObject to prevent duplication")]
    public MyObject AnotherOldObject
    {
      get { return _anotherOldObject; }
      set { _anotherOldObject = value; }
    }

    public MyObject NewBetterObject
    {
      get { return _anotherOldObject; }
      set { _anotherOldObject = value; }
    } 
}

Есть идеи об обходном пути? Мое лучшее решение - писать устаревшие в комментариях XML ...

Обновление: я использую .NET 2.0

Ответы [ 6 ]

33 голосов
/ 01 декабря 2008

РЕДАКТИРОВАТЬ : После прочтения статьи MS Connect выясняется, что в .Net 2.0 есть «функция», благодаря которой ObsoleteAttribute эквивалентен XmlIgnoreAttribute без какого-либо уведомления в документации. Поэтому я собираюсь пересмотреть свой ответ, чтобы сказать, что единственный способ получить свой торт и съесть его в этом случае - это следовать совету @ Will и реализовать сериализацию вручную . Это будет вашим единственным будущим способом включения устаревших свойств в ваш XML. Это не очень красиво в .Net 2.0, но .Net 3.0+ может облегчить жизнь.

С XmlSerializer :

Объекты, помеченные как устаревшие, больше не сериализуются. В .NET Framework 3.5 класс XmlSerializer больше не сериализует объекты, помеченные как [устаревшие].

10 голосов
/ 03 августа 2011

Другой обходной путь - подписаться на XmlSerializer.UnknownElement при создании сериализатора для типа данных, а затем исправить старые данные таким образом.

http://weblogs.asp.net/psteele/archive/2011/01/31/xml-serialization-and-the-obsolete-attribute.aspx

Возможно, стоит рассмотреть возможность использования метода подписки в качестве статического метода в классе для типа данных.

static void serializer_UnknownElement(object sender, XmlElementEventArgs e)
{
    if( e.Element.Name != "Hobbies")
    {
        return;
    }

    var target = (MyData) e.ObjectBeingDeserialized;
    foreach(XmlElement hobby in e.Element.ChildNodes)
    {
        target.Hobbies.Add(hobby.InnerText);
        target.HobbyData.Add(new Hobby{Name = hobby.InnerText});
    }
}
3 голосов
/ 23 июля 2013

Я много боролся с этим - нет другого решения, кроме как выполнить сериализацию вручную или использовать другой сериализатор.

Однако вместо написания прокладок для каждого устаревшего свойства, которое быстро становится проблемой, вы можете рассмотреть возможность добавления префикса Obsolete к именам свойств (например, Foo становится ObsoleteFoo. Это не будет генерировать предупреждение компилятора, подобное Атрибут будет, но по крайней мере он виден в коде.

2 голосов
/ 01 декабря 2008

1) WAG: попробуйте добавить свойство XmlAttributeAttribute к свойству; возможно, это заменит устаревший атрибут
2) PITA: внедрить IXmlSerializable

1 голос
/ 16 марта 2016

Да, я согласен с маркировкой вещей «Устаревшие», мы делаем это с помощью значений Enum

/// <summary>
/// Determines the swap file location for a cluster.
/// </summary>
/// <remarks>This enum contains the original text based values for backwards compatibility with versions previous to "8.1".</remarks>
public enum VMwareClusterSwapFileLocation
{

    /// <summary>
    /// The swap file location is unknown.
    /// </summary>
    Unknown = 0,

    /// <summary>
    /// The swap file is stored in the virtual machine directory.
    /// </summary>
    VmDirectory = 1,

    /// <summary>
    /// The swap file is stored in the datastore specified by the host.
    /// </summary>
    HostLocal = 2,

    /// <summary>
    /// The swap file is stored in the virtual machine directory. This value is obsolete and used for backwards compatibility.
    /// </summary>
    [XmlElement("vmDirectory")]
    ObseleteVmDirectory = 3,

    /// <summary>
    /// The swap file is stored in the datastore specified by the host. This value is obsolete and used for backwards compatibility.
    /// </summary>
    [XmlElement("hostLocal")]
    ObseleteHostLocal = 4,




}
0 голосов
/ 01 декабря 2008

Вы можете попробовать следующий обходной путь:

добавить метод с именем

ShouldSerializeOldObject ()
{
   return true;
}

ShouldSerializeAnotherOldObject ()
{
   return true
}

это может переопределить устаревший атрибут

...