2

直到昨晚,我一直在使用 .NET 中的各种库来解析 XML——XmlDocument而且XDocument主要是。我不知道为什么我不早点研究这个问题,但我突然想到 .NET 中一定有一些东西可以免费为您提供类序列化/反序列化,当然这以XmlSerializer类的形式出现.

果然,通过几行代码,我就可以轻松地进行序列化和反序列化(虽然在我现在写的代码中,我只需要反序列化),不再需要花费几个小时左右的时间编写我自己的类来与其他库一起执行此操作,以及必要的单元测试。但问题是我希望我的属性是只读的。如果我将 setter 设为私有,则在创建 XmlSerializer 时会出现此错误:

无法生成临时类(结果=1)。错误 CS0200:无法将属性或索引器“MyProperty”分配给——它是只读的

看起来这是一个无法解决的问题,所以必须有一个解决方法。

果然,我找到了这个信息,这表明如果你放弃自动属性并返回私有字段,你可以让代码编译。不幸的是,虽然它可以编译,但当您执行代码时,它实际上并没有反序列化数据。停止我的应用程序后,我注意到消息窗口中有几个条目是这样说的:

找不到元素“MyProperty”的架构信息。

这是因为没有代码为 MyProperty 赋值,因为 XmlSerializer 不知道如何处理私有字段!!!

我在 StackOverflow 上找到了一个答案,该答案提出了另一种解决方案,即使用DataContractSerializer我以前从未听说过的 a 。我对我的班级进行了必要的代码更改,但最终得到了与上面相同的消息。我运行了代码以确保在反序列化 XML 时不会设置类成员。

我在想,在我的特殊情况下,我要么接受它并允许成员被覆盖(坏),要么我回到我原来的做事方式,即只写所有的序列化/反序列化代码我。我在这里做错了什么,还是不可能允许像 XmlSerializer 这样的类在反序列化期间设置类的私有成员,同时使类的使用者无法覆盖其成员?

更新还有另一篇文章展示了另一种对私有属性进行反序列化的方法,但我只是尝试过,它也不起作用。

以下是我尝试反序列化的类的一些示例:

[Export]
[DataContract]
public class Configuration
{
    [DataMember(Name="Port")]
    private int _port;
    public int Port { get { return _port; }}
}

结果:使用 XmlSerializer 反序列化时,没有错误,但是当我的 XML 文件的 Port 值为 1 时,_port 和 Port 的值为 0,例如<Port>1</Port>.

另一个例子:

[Export]
public class Configuration
{
    public int Port { get; set; }
}

结果:反序列化很好,但我不想要公共设置器。

我像这样反序列化类:

XmlSerializer serializer = new XmlSerializer(typeof(Configuration));
FileStream reader = new FileStream( "config.xml", FileMode.Open);
Configuration Config = (Configuration)serializer.Deserialize( reader);
reader.Close();
4

3 回答 3

3

我没有一个好的答案,但我有几个不好的答案。没有特别的顺序:

  1. 您可以创建具有 r/w 属性的纯数据传输对象,并将其用于序列化/反序列化。然后,您可以通过使用 DTO 进行构造来初始化您的不可变业务对象。

  2. 您提到的两个序列化程序类还允许通过属性和代码的组合来覆盖它们的行为。这可能足以解决您的问题,但可能比它的价值更多。

于 2010-08-07T15:40:07.410 回答
1

这不是使用哪种 XML 序列化方法的问题,而是关于序列化本身的问题(尝试使用二进制序列化,您会得到相同的错误)。

如果您无法更改该属性以允许执行默认序列化方法,则:

  1. 实现 ISerializable 接口。
  2. 在您的 GetObjectData 实现中,将值添加到为您需要记录的每个字段传递的 SerializationInfo 参数。
  3. 添加一个构造函数(它不必是公共的),它接受一个 SerializationInfo 参数和一个 StreamingContext 参数。在此构造函数中,您可以从序列化期间写入的 SerializationInfo 中读取数据,从而生成反序列化的对象。

现在,这似乎有点像回到手动序列化,但是它只需要在问题中的类上完成,它还使您的类可以通过其他机制进行序列化。

于 2010-08-07T16:11:53.593 回答
0

我认为,最终,这个问题的正确答案是,如果您需要反序列化(序列化不是问题)私有数据,那么您希望避免使用 XmlSerializer 和 DataContractSerializer。我仍然希望我是错的,但最后,乔恩可能是对的——我将需要使用 ISerializable,或者按照我迄今为止所做的方式来做。

当我决定使用一个具有公共属性的类来允许反序列化,然后用另一个类包装它时,我今晚又碰了壁。我不想将可反序列化的类公开——我希望它是一个只公开只读属性的私有类。那么,问题在于 XmlSerializable 不能处理私有的类。

我现在可以将课程公开,我可能会这样做只是为了让事情先正常运行,但我会走一条不同的路线,因为必须公开该课程是没有意义的。

于 2010-08-08T03:43:10.583 回答