【问题标题】:Why isn't my public property serialized by the XmlSerializer?为什么我的公共属性没有被 XmlSerializer 序列化?
【发布时间】:2010-10-09 04:38:31
【问题描述】:

这是我多年来一直在苦苦挣扎的一个,所以我想我会在某个地方记录下来。 (对提问和回答问题表示歉意。)

(C# .net 2.0) 我有一个由 XmlSerializer 序列化的类,我添加了一个新的公共属性,但是它没有包含在输出 XML 中。

在我能找到的任何地方的文档中都没有提到它,但是公共属性必须有一个 set 和一个 get 才能被序列化!我猜这是因为它假设如果你要序列化,那么你会想要从同一个文件反序列化,所以只序列化同时具有 set 和 get 的属性。

【问题讨论】:

    标签: c# .net xml-serialization


    【解决方案1】:

    如前所述,大多数属性必须同时具有 getter 和 setter;主要的例外是列表 - 例如:

    private readonly List<Foo> bar = new List<Foo>();
    public List<Foo> Bar {get { return bar; } } // works fine
    

    这会很好用;但是,如果XmlSerializer 找到一个 setter - 它要求它是公开的;以下将工作:

    public List<Foo> Bar {get; private set;} // FAIL
    

    它可能无法序列化的其他原因:

    • get 和 set 不公开(或者字段为 readonly
    • 它有一个[DefaultValue] 属性,并且具有该值
    • 它有一个返回 false 的公共 bool ShouldSerializeFoo() 方法
    • 它有一个返回 false 的公共 bool FooSpecified {get;set;} 属性或字段
    • 标记为[XmlIgnore]
    • 标记为[Obsolete]

    其中任何一个都会导致它无法序列化

    【讨论】:

    • 在某些情况下,返回集合的属性不需要集合,但必须在构造函数中对其进行初始化......对于没有公共构造函数的集合来说就是这种情况。但是这种行为对我来说似乎有点不一致......
    • 如果属性标记为[Obsolete],它也不会序列化。
    • 有一个 getter 但没有 setter...哇,这很烦人,感谢这篇文章。
    • @user384080 大多数序列化程序希望双向使用 - 即同时用于序列化和反序列化。如果没有set,则在反序列化过程中将无法重新创建对象,因为它无法赋值。现在,有时序列化程序可以解决这个问题,有时他们只是序列化它而不承诺反序列化;但是,XmlSerializer 选择“忽略属性”方法。
    • [Foo]Specified 序列化程序“gotcha”让我难过。使用带有非常糟糕的文档的第 3 方 XML,该文档具有 AmountPaid 公共十进制属性和 AmountPaidSpecified 公共 bool 属性。 AmountPaidSpecified 的默认值为 false,因为它是一个布尔值。所以,AmountPaid 永远不会被序列化!通过将 AmountPaidSpecified 设置为 true,瞧!,AmountPaid 会被序列化。
    【解决方案2】:

    关于 getter+setter 的观点在“Intro to Xml Serialization”页面的第 3 段中提出。它实际上是在一个呼叫框。不能错过!

    Intro-to-XML Serialization http://www.freeimagehosting.net/uploads/2f04fea2db.png

    (在 Freeimagehosting.net 上玩得太开心了)

    【讨论】:

    • 啊,它在那里是对的,但你不能错过它是错误的:)
    • 我曾经读过一项研究,该研究称人们忽略标题并在文章中标注框,而不是忽略常规文本。 ??适得其反。
    • @Cheeso : 没错,我从不查看 Google 搜索结果中的赞助链接 ;)
    • 我很好奇为什么支持只读集合,但不支持只读属性..?
    • 答案中链接的图片已损坏
    【解决方案3】:

    返回 null 的属性也不会被序列化!

    【讨论】:

    • 啊,但是返回 null 的可空类型属性是!我这里有这个 public int? GroupTypeId 属性在此处被序列化为 XML -
    【解决方案4】:

    如果你的类继承了一个列表并且也有它自己的成员,那么只有列表中的元素会被序列化。您的班级成员中存在的数据不会被捕获。 花了一些时间弄清楚这一点!

    【讨论】:

    • 啊,但是为什么呢?有人知道吗?
    【解决方案5】:

    如果您不想实现正确的 Setter(因为也许您既不想反序列化或更改对象值),您可以使用像 set { } 这样的虚拟设置器,这样 XMLSerializer 就可以工作,但什么也没有如果你使用 Setter 会发生...

    i.E.

    public string ID { get { return _item.ID.ToString(); } set { } }
    

    【讨论】:

    • 如果初级程序员使用此 setter 属性并认为它正在设置值,这可能是一个问题。还是更喜欢“抛出新异常……”
    【解决方案6】:

    关于集合序列化的另一件事:

    XmlSerializer 忽略接口集合!

    我的意思是忽略。虽然您会遇到以下行的异常:

    public IFoo Foo { get; set; }
    

    您将不会获得以下例外:

    public ICollection<IFoo> LotsOfFoos { get { return this.fooBackingField; } }
    

    【讨论】:

      【解决方案7】:

      您可以实现IXmlSerializer 并手动进行序列化,并从序列化属性中受益,反之亦然,使用构造函数/私有字段分配反序列化它们。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-11-10
        • 2014-01-20
        • 2018-03-06
        • 1970-01-01
        • 2015-09-10
        相关资源
        最近更新 更多