【问题标题】:How can I call the constructor before deserialisation?如何调用构造函数进行反序列化?
【发布时间】:2016-01-07 16:35:46
【问题描述】:

我尝试通过数据协定序列化对自定义类进行序列化和反序列化。 序列化效果很好。但是,在反序列化时,我遇到了一个问题,因此(source):

反序列化对象时不调用构造函数。

问题是我在构造函数中做了一些初始化。 这包括一些数据结构。

不调用构造函数,数据结构为null,反序列化期间调用setter函数失败。

在反序列化过程之前或期间,如何在使用任何访问器之前调用构造函数或初始化对象?

我可以通过属性将一些方法声明为回调,如下所示(同一来源):

// This method is called after the object 
// is completely deserialized. Use it instead of the
// constructror.
[OnDeserialized] 
void OnDeserialized(StreamingContext context)
{
    fullName = firstName + " " + lastName;
}

但看起来它们都是在反序列化之后触发的。

我必须切换到 XML 序列化吗?

【问题讨论】:

  • 这应该在您序列化对象之前已经发生。所以再做一次就错了。
  • 是的,使用OnDeserialized 方法可以初始化您的字段。在此之前没有任何东西可以访问这些字段/属性。
  • @HansPassant 反序列化是独立发生的。在程序的执行过程中,我只加载序列化的数据,并希望将其反序列化为一个对象。序列化甚至没有在反序列化之前发生(在这个程序实例中)。在此之前我不太确定如何调用构造函数。
  • @SriramSakthivel 这是不正确的。同样,cmets 声明它发生在反序列化之后,我的结果同意这一点:在调用函数之前使用访问器。我不能用它来初始化字段。

标签: c# serialization deserialization datacontractjsonserializer


【解决方案1】:

使用签名创建构造函数

protected YourClassName(SerializationInfo info, StreamingContext context)
{
}

让你的班级实现ISerializable。在序列化时它调用ISerializable.GetObjectData() 在反序列化时它调用上面的构造函数。

请参阅 MSDN 上的 Custom Serialization: Implementing the ISerializable Interface

如果您实际上不需要在构造函数中完成工作,您可以使用属性[OnDeserializing] 而不是[OnDeserialized] 来完成工作之前 反序列化而不是之后。

[OnDeserializing]
private void SetValuesOnDeserializing(StreamingContext context)
{
    // Code not shown.
}

注意:如果您的对象图中有多个 [OnDeserializing] 方法,则调用它们的顺序不是错误的。

【讨论】:

  • The documentation lies when it says that "任何给定的类型都可以支持无、一种或多种序列化技术。",因为我无法实现ISerializable 并使用DataContractAttribute同时。另一方面,[OnDeserializing] 效果很好。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-12-29
  • 2011-07-09
  • 2023-03-10
  • 2020-10-20
  • 1970-01-01
  • 2016-07-13
  • 2012-12-06
相关资源
最近更新 更多