Устаревший атрибут заставляет свойство игнорировать 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
Ответы
Ответ 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,
}