gpt4 book ai didi

.net - 重构代码后使用 NetDataContractSerializer 反序列化的问题

转载 作者:行者123 更新时间:2023-12-04 21:23:53 24 4
gpt4 key购买 nike

我有一种情况,我正在使用 NetDataContractSerializer 序列化一些 .NET 对象,并将 XML 存储在数据库中,以此来记住应用程序中这些对象的状态。最近我刚刚遇到第一种情况,其中一些属性和类型名称的代码重构导致无法反序列化此 XML 数据。

到目前为止,我已经提出了两种不同的攻击计划,用于处理版本兼容性中断,例如使用 NetDataContractSerializer 本身提供的工具来控制反序列化或直接转换 XML。根据我的实验和研究,似乎可以使用 custom SerializationBinder 反序列化为不同的类型。和属性名称/类型更改可以通过实现 ISerializable 或通过实现 ISurrogateSelector 和 ISerializationSurrogate 编写序列化代理来解决。不幸的是,这种首选机制还没有被淘汰,除非我可以显示,否则它似乎使用代理在序列化数据的版本之间移动是不可能使用 NetDataContractSerializer 的,这是由于一些无法解释的 design decision by Microsoft .微软的建议是在双方都使用相同的序列化,这完全违背了使用代理来帮助在类型名称更改或移动到不同的命名空间或程序集的情况下的目的。

To fix it, please use the same NetDataContractSerializer instance or another instance that is also initialized with a compatible SurrogateSelector.



此解释与 an MSDN article 冲突。这说明了使用自定义绑定(bind)器来替换类型以及处理序列化结构中的其他更改。

During deserialization, the formatter sees that a binder has been set. As each object is about to be deserialized, the formatter calls the binder's BindToType method, passing it the assembly name and type that the formatter wants to deserialize. At this point, BindToType decides what type should actually be constructed and returns this type.

Note that the original type and the new type must have the same exact field names and types if the new type uses simple serialization via the Serializable custom attribute. However, the new version of the type could implement the ISerializable interface and then its special constructor will get called and the type can examine the values in the SerializationInfo object and determine how to deserialize itself.



因此,要么我将能够让 NetDataContractSerializer 将我的 V1 XML 反序列化为我的 V2 类型,要么我将不得不手动转换 XML。如果有人可以证明 NetDataContractSerializer 的 SerializationInfo 在使用 ISerializable 或使用序列化代理时确实有效,这将是优秀的,或者至少比微软给出的解释更好,否则我可能会发布一个新问题来辩论最佳方式在 .NET 中直接转换旧的 XML。

2011 年 8 月 16 日更新:
经过一些实验后,如果被序列化的原始类型实现 ISerializable,则 ISerializable 和序列化代理技术似乎都可以正常工作,否则如果该类型仅使用 [Serializable] 属性,则似乎对象图中的每个字段都缺少一些有值(value)的类型信息以额外属性的形式。

使用 的示例[可序列化] 属性
<OldClass2 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" z:Id="1" z:Type="NdcsSurrogateTest.OldClass2" z:Assembly="NdcsSurrogateTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/NdcsSurrogateTest">
<_stable z:Id="2">Remains the same</_stable>
<_x003C_OldProperty_x003E_k__BackingField>23</_x003C_OldProperty_x003E_k__BackingField>
</OldClass2>

实现示例 可序列化 :
<OldClass2 xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns:x="http://www.w3.org/2001/XMLSchema" z:Id="1" z:Type="NdcsSurrogateTest.OldClass2" z:Assembly="NdcsSurrogateTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" xmlns:z="http://schemas.microsoft.com/2003/10/Serialization/" xmlns="http://schemas.datacontract.org/2004/07/NdcsSurrogateTest">
<_stable z:Id="2" z:Type="System.String" z:Assembly="0" xmlns="">Remains the same</_stable>
<_x003C_OldProperty_x003E_k__BackingField z:Id="3" z:Type="System.Int32" z:Assembly="0" xmlns="">23</_x003C_OldProperty_x003E_k__BackingField>
</OldClass2>

当使用带有自定义绑定(bind)器的 NetDataContractSerializer 来反序列化第一个示例以更改类型,然后在该类型上实现 ISerializable 或提供一个代理选择器来指定基本上满足 ISerializalbe 角色的序列化代理时,您将在 ISerializationSurrogate 中看到一个空的 SerializationInfo .SetObjectData 方法。在第二个示例中处理 xml 时,SerializationInfo 似乎获得了正确的信息,并且事情按预期工作。

我的结论是,NetDataContractSerializer 为仅通过 SerializableAttribute 支持序列化的类型生成的默认 XML 将与使用 ISerializable 或序列化代理技术的反序列化不兼容,因为缺少类型信息。因此,为了使 NetDataContractSerializable 的使用更具前瞻性,应该自定义序列化以确保 XML 中包含此类型信息,以便以后可以自定义反序列化,而无需手动转换源 XML。

最佳答案

是的,如果您使用序列化,您必须有一个经过深思熟虑的数据迁移路径。您提到的解决方案是我个人会做的,包括检查将反序列化的代码。如果检测到旧版本,请进行小的转换,使其与新格式匹配,然后根据需要继续操作。一旦转换了所有数据,该代码就可以在 future 的版本中被淘汰。

关于.net - 重构代码后使用 NetDataContractSerializer 反序列化的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7078856/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com