我正在使用 DataContractJsonSerializer。
目前,我的序列化对象包含“Settings”类的成员
现在,我想扩展我的支持并序列化任何实现 ISettings 接口的类。
[DataContract(Namespace = "")]
[KnownType(typeof(SystemSettings))]
[KnownType(typeof(PrivateSettings))]
public class Data
{
[DataMember]
public ISettings settings { get; set; }
}
public interface ISettings
{
}
[DataContract(Namespace = "")]
public class SystemSettings : ISettings
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string SysName { get; set; }
}
[DataContract(Namespace = "")]
public class PrivateSettings : ISettings
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string PrivateName { get; set; }
}
这工作得很好,因为序列化数据包含对象的类型
<?xml version="1.0" encoding="utf-8"?>
<root type="object">
<settings __type="SystemSettings" type="object">
<Name>System Settings</Name>
<SysName>New System</SysName>
</settings>
</root>
我的问题是向后兼容性。现有序列化文件不包含对象类型 (__type="SystemSettings")。 当将旧数据反序列化到我的类中时,我得到
"{"Unable to cast object of type 'System.Object' to type 'JsonSerializer.ISettings'."}"
有办法解决这个问题吗? 我可以指示序列化器为接口实例化什么默认类型吗?
谢谢!
是的,有办法。工作方针是保留老品种、引进新品种。您不应该违反您的数据合同。为了避免破坏,在一般情况下,您应该只扩展它,而不删除旧类型。换句话说,您的数据合约迁移应该是“增量”的。在极少数情况下,您可以进行非增量迁移,但需要特别注意。 您的软件迁移后,您会面临数据混合的情况。例如,有些文件是使用较旧的软件创建的,有些文件是使用较新的软件版本创建的。在所有情况下您都需要处理这些数据。例如,您可以重新解释旧数据以适应新的软件设计。
但是,在开发过程中,您可以(也可以不)选择多次破坏数据合同。我最近推出的政策是允许的,但仅限于
0.…alpha软件版本。我只是警告团队,尤其是测试人员,数据契约随时可能被破坏,所以他们只能手动修复测试数据。成功了。 要了解其他含义并获得更多想法,另请参阅
我最近的回答[System.Obsolete]
和
System.Version
类型的数据协定成员可以帮助应对棘手的数据协定迁移问题。