如何将XML文件反序列化为具有只读属性的类?
我有一个用作设置类的类,该类已序列化为XML文件,管理员可以编辑该文件以更改应用程序中的设置。 (设置比App.config所允许的要复杂一些。)
我正在使用XmlSerializer类对XML文件进行反序列化,并且希望它能够设置属性类,但是我不希望其他使用该类/程序集的开发人员能够通过代码设置/更改属性。我可以通过XmlSerializer类来实现这一点吗?
添加更多细节:这个特定的类是Collection,根据FxCop的说法,XmlSerializer类对反序列化只读的collection具有特殊的支持,但是我还没有找到更多的信息。违反的规则的确切详细信息是:
Properties that return collections should be read-only so that users cannot entirely replace the backing store. Users can still modify the contents of the collection by calling relevant methods on the collection. Note that the XmlSerializer class has special support for deserializing read-only collections. See the XmlSerializer overview for more information.
这正是我想要的,但是它是怎么做的呢?
编辑:好的,我想我在这里有点疯狂。就我而言,我要做的就是在构造函数中初始化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; }
}
}
解决方案
我不认为我们可以使用自动序列化,因为该属性是只读的。
我的做法是实现ISerializable接口并手动执行。我们将可以从此处设置内部值。
但是,如果子对象(公开为只读)可以自行进行序列化,则它们应该都可以正常工作。
我认为FxCop抱怨的规则是我们拥有类似以下内容的东西:
public List<MyObject> Collection
{
get { return _collection; }
set { _collection = value; }
}
不是吗如果没有,我们是否可以粘贴一些代码,以便我可以确切地知道我们在做什么?有几种方法可以完成上述所有操作:)
我们必须使用可变列表类型,例如ArrayList(或者IList IIRC)。
@Rob Cooper说对了,只需实现ISerializable接口,我们就可以对类的序列化和反序列化以及手动设置字段的方式进行自定义控制。这需要更多的工作量,但可以实现我们期望的目标。祝你好运。
@leppie的回复实际上是最接近的。这是XmlSerializer文档中的实际相关文本,有关更多详细信息,请参见我对以上问题的编辑:
The XmlSerializer gives special treatment to classes that implement IEnumerable or ICollection. A class that implements IEnumerable must implement a public Add method that takes a single parameter. The Add method's parameter must be of the same type as is returned from the Current property on the value returned from GetEnumerator, or one of that type's bases. A class that implements ICollection (such as CollectionBase) in addition to IEnumerable must have a public Item indexed property (indexer in C#) that takes an integer, and it must have a public Count property of type integer. The parameter to the Add method must be the same type as is returned from the Item property, or one of that type's bases. For classes that implement ICollection, values to be serialized are retrieved from the indexed Item property, not by calling GetEnumerator.

