过时的属性导致XmlSerialization忽略属性

时间:2008-12-01 14:28:06

标签: c# .net-2.0 xml-serialization attributes

我正在重构一些序列化为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 个答案:

答案 0 :(得分:33)

编辑After reading a MS Connect article,似乎.Net 2.0有一个'功能',它使ObsoleteAttribute等同于XmlIgnoreAttribute,而不会在文档中发出任何通知。因此,我将修改我的答案,说在这种情况下,获取蛋糕和吃它的唯一方法是遵循@Will的建议和implement serialization manually。这将是您在XML中包含过时属性的唯一未来证明方式。它在.Net 2.0中并不漂亮,但.Net 3.0+可以让生活更轻松。

来自XmlSerializer

  

标记有过时属性的对象不再序列化   在.NET Framework 3.5中,XmlSerializer类不再序列化标记为[已废弃]的对象。

答案 1 :(得分:10)

另一种解决方法是在为数据类型创建序列化程序时订阅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});
    }
}

答案 2 :(得分:3)

我一直在努力解决这个问题 - 除了手动或使用其他序列化程序进行序列化之外,没有其他解决方案。

但是,您可以考虑在属性名称中添加Obsolete前缀(例如Foo变为ObsoleteFoo,而不是为每个过时属性编写填充程序,这很快就会变成一种痛苦。生成类似于属性的编译器警告,但至少它在代码中可见。

答案 3 :(得分:2)

1)WAG:尝试将XmlAttributeAttribute添加到属性中;也许这会覆盖ObsoleteAttribute
2)PITA:实现IXmlSerializable

答案 4 :(得分:1)

是的,我同意用名称来标记事物"过时"我们用枚举值

来做到这一点
/// <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,




}

答案 5 :(得分:0)

您可以尝试以下解决方法:

添加名为

的方法
ShouldSerializeOldObject ()
{
   return true;
}

ShouldSerializeAnotherOldObject ()
{
   return true
}

这可能会覆盖过时的属性