序列化/反序列化和非默认的构造函数(Serialization/Deserialization an

2019-08-03 05:13发布

考虑这个类:

[Persistable]
public sealed class FileMoveTask : TaskBase
{
     [PersistMember]
     public string SourceFilePath { get; private set;}

     [PersistMember]
     public string DestFilePath { get; private set;}

     public FileMoveTask(string srcpath, string dstpath)
     {
         this.SourceFilePath = srcpath;
         this.DestFilePath = dstpath;

         //possibly other IMPORTANT initializations
     }

     //code
}

我能坚持这个类的对象,通过序列化所有属性成员PersistMember 。 但我现在面临反序列化过程的一些问题(设计问题)。 特别是,问题出在“其他可能的重要初始化”,这可能会在构造函数中存在,而程序员可能决定进行一些成员持久化(即不添加PersistMember他们)可能是因为这没有任何意义。

在这种情况下,我怎么会反序列化对象完全相同的状态,因为它是? 我想,这个问题归结为:我怎么会调用非默认构造函数,传递相同的参数给它,这是之前通过呢? 有没有办法做到这一点? 我们可以做一些规则可以由编译器(排序元编程)执行呢? 构造属性可以帮助吗?

Answer 1:

您可以解决两种方式。 使用约定优于配置(命名构造函数参数的属性,不包括默认构造函数):

[Persistable]
public sealed class FileMoveTask : TaskBase
{
     [PersistMember]
     public string SourceFilePath { get; private set;}

     [PersistMember]
     public string DestFilePath { get; private set;}

     public FileMoveTask(string sourceFilePath, string destFilePath)
     {
         this.SourceFilePath = srcpath;
         this.DestFilePath = dstpath;

         //possibly other IMPORTANT initializations
     }

     //code
}

明确你的属性标记构造函数的参数,并搜索已标记的构造函数:

[Persistable]
public sealed class FileMoveTask : TaskBase
{
     [PersistMember]
     public string SourceFilePath { get; private set;}

     [PersistMember]
     public string DestFilePath { get; private set;}

     public FileMoveTask([PersistMember("SourceFilePath")]string srcpath, [PersistMember("DestFilePath")]string dstpath)
     {
         this.SourceFilePath = srcpath;
         this.DestFilePath = dstpath;

         //possibly other IMPORTANT initializations
     }

     //code
}

属性或参数名称没有用了就知道要设置的属性,但要知道调用构造函数时所使用的从序列化的数据信息。



Answer 2:

解决这个问题最简单的方法是使用现有的公知技术。 例如,看看那些在.NET框架中使用(你会发现巨大的差异是什么)其他序列化机制。

例如,在BinaryFormatter的 , SoapFormatter和DataContractSerializer的使用对于反序列化对象以下技术:

  1. 获得“原始”通过调用对象FormatterServices.GetUnitializedObject
  2. 调用构造的对象在单独序列化前方法(通过检查标记方法OnSerializingAttribute )。
  3. 反序列化对象的状态(通过检查相应的属性,了解哪些字段串行应该跳过哪些字段应该反序列化)。
  4. 呼叫序列化后方法上反序列化对象(通过检查标记方法OnSerializedAttribute )。

另一方面XmlSerializer的使用完全不同的算法:它要求应作为“预系列化”和“序列化后”的步骤参数的构造函数。

所以我的观点是,它完全取决于串行器的类型和其执行情况。 而在仍然需要从两个串行的作者和串行的消费者一些心力。

所以我强烈建议使用现有技术中的一种,但不是发明轮子(如添加一些其他的自定义属性还原对象的状态)。 你甚至可以使用现有属性来简化从.NET序列化设施,以自定义序列化机制的迁移(以及使用额外的属性,如NonSerializableAttrubite )。



文章来源: Serialization/Deserialization and non-default constructors