Подтвердить что ты не робот

Устаревший атрибут заставляет свойство игнорировать XmlSerialization

Я рефакторинг некоторых объектов, которые сериализуются в 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

4b9b3361

Ответ 1

EDIT: После прочтения статьи MS Connect, похоже, что .Net 2.0 имеет "функцию", где он делает ObsoleteAttribute эквивалентным XmlIgnoreAttribute без любое уведомление в документации. Поэтому я собираюсь пересмотреть свой ответ, чтобы сказать, что единственный способ получить ваш торт и съесть его тоже в этом случае - следовать советам @Will и реализовать сериализацию вручную. Это будет ваш единственный надежный способ включения устаревших свойств в ваш XML. Это не очень хорошо .Net 2.0, но .Net 3.0+ может облегчить жизнь.

От XmlSerializer:

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

Ответ 2

Другим обходным решением является подписка на 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

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

Ответ 4

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

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

Ответ 5

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

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

ShouldSerializeOldObject ()
{
   return true;
}

ShouldSerializeAnotherOldObject ()
{
   return true
}

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

Ответ 6

Да, я согласен с маркировкой вещей с именем "Устаревший", мы делаем это с помощью значений 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,




}