【问题标题】:How do I deserialize an XML file into a class with a read only property?如何将 XML 文件反序列化为具有只读属性的类?
【发布时间】:2008-09-25 14:40:28
【问题描述】:

我有一个类用作设置类,该类被序列化为 XML 文件,然后管理员可以对其进行编辑以更改应用程序中的设置。 (设置比App.config 允许的要复杂一些。)

我正在使用XmlSerializer 类来反序列化 XML 文件,我希望它能够设置属性类,但我不希望使用该类/程序集的其他开发人员能够设置/更改通过代码的属性。我可以使用 XmlSerializer 类实现这一点吗?

添加更多细节:这个特定的类是一个集合,根据 FxCop 的说法,XmlSerializer 类对反序列化只读集合具有特殊的支持,但我无法找到更多关于它的信息。这违反的规则的确切细节是:

返回集合的属性应该是只读的,这样用户就不能完全替换后备存储。用户仍然可以通过调用集合上的相关方法来修改集合的内容。请注意,XmlSerializer 类对反序列化只读集合具有特殊支持。有关详细信息,请参阅 XmlSerializer 概述。

这正是我想要的,但它是如何做到的呢?

编辑:好的,我想我在这里有点疯了。就我而言,我所要做的就是在构造函数中初始化 Collection 对象,然后删除属性设置器。然后 XmlSerializable 对象实际上知道使用 Collection 对象中的 Add/AddRange 和 indexer 属性。以下确实有效!

public class MySettings
{
    private Collection<MySubSettings> _subSettings;
    public MySettings()
    {
       _subSettings = new Collection<MySubSettings>();
    }

    public Collection<MySubSettings> SubSettings
    {
         get { return _subSettings; }
    }
}

【问题讨论】:

  • 您实际上并没有从您的 SubSettings 属性返回一个只读集合,而是返回一个可以修改的集合。
  • 我不明白.. 你以前有什么?我的意思是,那只是阻止人们去 SubSettings = Blah;集合本身实际上不是只读的?
  • @Rob Cooper:在他的代码中,集合不是只读的。他仍然返回一个可变集合,他只是无法更改该类使用的引用。如果这是他的意图,那很好。
  • @Rob Cooper:是的,很抱歉,我的意思是 Collection 属性本身是只读的,我不希望我的班级的消费者重新实例化或修改它,而不是添加内容给它。抱歉,原来的问题不清楚。
  • 太棒了,我遇到了完全相同的问题。感谢您更新解决方案!

标签: c# .net xml xml-serialization


【解决方案1】:

您必须使用可变列表类型,例如 ArrayList(或 IList IIRC)。

【讨论】:

  • 是的,谢谢,它实际上是 IEnumerable 或 ICollection,但是是的,您的答案与我发现的非常接近。
【解决方案2】:

@Rob Cooper 说得对,只需实现ISerializable 接口,您就可以自定义控制您的类如何序列化和反序列化以及手动设置字段。这是一个多一点的腿部工作,但它会实现你想要的目标。祝你好运。

【讨论】:

    【解决方案3】:

    我认为您不能使用自动序列化,因为该属性是只读的。

    我的做法是实现ISerializable 接口并手动完成。您将能够从这里设置内部值。

    但是,如果您的子对象(以只读方式公开)可以自行序列化,那么它应该可以正常工作..

    我认为 FxCop 抱怨的规则是你有类似的东西:

    public List<MyObject> Collection
    {
       get { return _collection; }
       set { _collection = value; }
    }
    

    不是吗?如果没有,你能粘贴一些代码,这样我就可以看到你到底在做什么?有几种方法可以完成上述所有操作:)

    【讨论】:

    • 是的,感谢您的回答...我希望不必手动进行。事实证明,在这种情况下我实际上没有(见问题编辑)。如果它更复杂,我可能不得不走那条路。
    • 抱歉编辑延误,网站在提交前就宕机了! :D
    【解决方案4】:

    @leppie 的回答实际上是最接近的。这是 XmlSerializer 文档中的实际相关文本,有关更多详细信息,请参阅我对上述问题的编辑:

    XmlSerializer 对实现 IEnumerable 或 ICollection 的类进行特殊处理。实现 IEnumerable 的类必须实现采用单个参数的公共 Add 方法。 Add 方法的参数必须与从 GetEnumerator 返回的值的 Current 属性返回的类型相同,或者该类型的基数之一。除了 IEnumerable 之外,实现 ICollection(如 CollectionBase)的类必须具有一个采用整数的公共 Item 索引属性(C# 中的索引器),并且它必须具有一个整数类型的公共 Count 属性。 Add 方法的参数必须与从 Item 属性返回的类型相同,或者是该类型的基数之一。对于实现 ICollection 的类,要序列化的值是从索引的 Item 属性中检索的,而不是通过调用 GetEnumerator。

    【讨论】:

      猜你喜欢
      • 2012-12-24
      • 1970-01-01
      • 2020-08-28
      • 1970-01-01
      • 2017-11-07
      • 2016-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多