59

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

4

6 回答 6

41

编辑阅读 MS Connect 文章后,.Net 2.0 似乎有一个“功能”,它使 ObsoleteAttribute 等效于 XmlIgnoreAttribute 而文档中没有任何通知。所以我要修改我的答案,说在这种情况下,吃蛋糕的唯一方法是遵循@Will 的建议并手动实施序列化。这将是您在 XML 中包含 Obsolete 属性的唯一未来证明方式。它在 .Net 2.0 中并不漂亮,但 .Net 3.0+ 可以让生活更轻松。

XmlSerializer

标记为 Obsolete 属性的对象不再序列化 在 .NET Framework 3.5 中,XmlSerializer 类不再序列化标记为 [Obsolete] 的对象。

于 2008-12-01T14:34:43.937 回答
11

另一种解决方法是在为数据类型创建序列化程序时订阅 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});
    }
}
于 2011-08-02T21:47:23.640 回答
3

我一直在为此苦苦挣扎——除了手动进行序列化或使用另一个序列化程序之外,没有其他解决方案。

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

于 2013-07-23T19:50:14.863 回答
2

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

于 2008-12-01T14:35:25.620 回答
2

是的,我同意用名称“过时”标记事物,我们使用 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,




}
于 2016-03-16T14:15:56.637 回答
0

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

添加一个名为的方法

ShouldSerializeOldObject ()
{
   return true;
}

ShouldSerializeAnotherOldObject ()
{
   return true
}

这可能会覆盖过时的属性

于 2008-12-01T14:45:49.140 回答