重构代码后使用 NetDataContractSerializer 进行反序列化时出现问题

2024-01-08

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

到目前为止,我已经针对如何处理版本兼容性中断提出了两种不同的攻击计划,例如使用 NetDataContractSerializer 本身内可用的设施来控制反序列化或直接转换 XML。根据我的实验和研究,似乎可以使用自定义SerializationBinder http://msdn.microsoft.com/en-us/library/ee358766.aspx属性名称/类型更改可以通过实现 ISerialized 或通过实现 ISurrogateSelector 和 ISerializationSurrogate 编写序列化代理来解决。不幸的是,这种首选机制尚未成功,除非我可以证明,否则使用 NetDataContractSerializer 不可能使用代理在序列化数据的版本之间移动,这是由于一些无法解释的原因微软的设计决策 https://connect.microsoft.com/VisualStudio/feedback/details/678627/iserializationsurrogate-loaded-from-isurrogateselector-in-netdatacontractserializer-receives-no-serializationinfo。微软建议的是在两侧使用相同的序列化,这完全违背了使用代理来帮助类型名称更改或移动到不同的命名空间或程序集中的情况的目的。

要修复此问题,请使用相同的 NetDataContractSerializer 实例或 另一个实例也用兼容的初始化 代理选择器。

这个解释与MSDN 文章 http://msdn.microsoft.com/en-us/magazine/cc188950.aspx其中涉及使用自定义绑定器来替换类型以及处理序列化结构中的其他更改。

在反序列化期间,格式化程序会发现绑定程序已设置。 当每个对象即将被反序列化时,格式化程序调用 binder 的 BindToType 方法,向其传递程序集名称和类型 格式化程序想要反序列化。此时,BindToType 决定 实际应该构造什么类型并返回该类型。

请注意,原始类型和新类型必须具有完全相同的字段 名称和类型(如果新类型通过以下方式使用简单序列化) 可序列化的自定义属性。然而,新版本的类型 可以实现 ISerialized 接口及其特殊的 构造函数将被调用,类型可以检查中的值 SerializationInfo 对象并确定如何反序列化自身。

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

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

使用示例[可序列化]属性

<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>

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

我的结论是,由于缺乏类型信息,NetDataContractSerializer 为仅通过 SerializedAttribute 支持序列化的类型生成的默认 XML 将与使用 ISerialized 或序列化代理技术的反序列化不兼容。因此,为了使 NetDataContractSerialized 的使用更加面向未来,应该自定义序列化以确保此类型信息包含在 XML 中,以便可以自定义以后的反序列化,而无需手动转换源 XML。


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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

重构代码后使用 NetDataContractSerializer 进行反序列化时出现问题 的相关文章

  • 如何查找 Visual Studio 项目的 .NET Framework 版本?

    我在 Visual Studio 中有一个项目 如何找出它适用于哪个 NET Framework 版本 这取决于 Visual Studio 的版本 In 2002 所有项目均使用 Net 1 0 In 2003 所有项目均使用 Net 1
  • Castle.Windsor可以自动解析具体类型吗

    我们正在评估 C 项目的 IoC 容器 Unity 和 Castle Windsor 都表现出色 我喜欢 Unity 的一件事 NInject 和 StructureMap 也这样做 是 显而易见如何构造它们的类型不必向 IoC 容器注册
  • .NET 自然语言处理工具包 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 您能给我一些用于 NET 中自然语言处理的工具包和库吗 有类似 UIMA for NET 的工具吗 有SharpNLP http shar
  • 在 C#/VB.NET 或 C++ Win32 中启用/禁用 Aero

    如何在 C NET 或 C Win32 中禁用航空效果 这是我在 C C 中的测试代码 但仅在我的应用程序运行时才有效 include
  • 集合已修改;枚举操作可能无法执行 - 为什么?

    我正在枚举一个实现 IList 的集合 并且在枚举期间我正在修改该集合 我收到错误 集合已修改 枚举操作可能无法执行 我想知道为什么在迭代期间修改集合中的项目时会出现此错误 我已经将 foreach 循环转换为 for 循环 但我想知道发生
  • 检查输出是否重定向

    我有一个用 C 编写的控制台应用程序 它处理一些数据然后打印结果 在结果可用之前 会有一个小动画 和不断更新的进度百分比 xx 显然 如果用户重定向我的应用程序的输出 这将被打印到输出重定向到的文本文件中 如果可能的话我想避免这种情况 那么
  • 快速变化的集合 MVVM WPF - 高 CPU 使用率和 UI 几乎冻结

    我正在开发一个带有数据网格的应用程序 它显示某些正在运行的 Windows 进程 在我的示例 Chrome 进程中 当选中复选框时 数据网格会加载进程 要求 显示每个进程的名称 内存使用情况 私有工作集 的 实时 信息 就像在 Window
  • 部署.Net应用程序

    我在部署 net windows 应用程序时确实有某些疑问 部署机器是否需要安装 Net框架 如果不是这样 我的应用程序安装程序 exe 是否包含编译器或类库与设置集成 另外 我可以将我的 net 应用程序部署在除windows 是否支持s
  • app.UseHsts() 和 app.UseExceptionHandler() 有什么区别?

    在 NET Core 应用程序的 Startup cs 文件中 默认情况下它使用 public void Configure IApplicationBuilder app IHostingEnvironment env if env Is
  • 指定自定义序列化程序时,错误详细信息未反序列化

    我正在使用自定义XmlObjectSerializer在我的应用程序中 为此 我替换XmlSerializerOperationBehavior with MyOperationBehavior看起来像这样 public class MyO
  • CLR 内部字符串常量吗?

    最近我一直在阅读字符串实习生池的工作原理 然而我一直没能找到这个问题的答案 如果我声明一个常量字符串变量 例如const string STR foo 这是否也会添加到实习生表中 只是为了澄清事情 CLR 不参与字符串驻留 Internin
  • 无法使用VS2010 SP1进入.NET框架源代码

    我按照步骤http blogs microsoft co il blogs arik archive 2010 07 12 step into net framework 4 0 source code aspx http blogs mi
  • 值类型数组如何存储在 .NET 对象堆中?

    在 NET中 诸如int之类的值类型对象存储在内存中 引用类型对象需要为引用和对象单独分配内存 并且对象存储在 NET对象堆中 而Array是在堆中创建的 那么int 等值类型的数组如何存储在堆中呢 这是否意味着值类型对象可以存储在堆中而无
  • COM Interop 挂起会冻结整个 COM 系统。如何取消COM调用

    我正在使用通过 COM Interop 包装器公开的第三方 dll 然而 其中一个 COM 调用经常冻结 至少不会返回 为了至少让我的代码更加健壮 我异步包装了调用 getDeviceInfoWaiter is a ManualResetE
  • EntLib5:登录应用程序块未记录到事件日志(例外:无法构造 LogWriter 类型)-任何人都可以帮忙吗?

    你好呀 我刚刚设置了 Enterprise Library 5 的日志记录应用程序块部分 我认为我已经完成了正确的操作 但它没有记录到事件日志 它在写入方法上出错并给出了以下异常 The type LogWriter cannot be c
  • invalidate方法有什么作用?

    什么是invalidate方法做在winform app Invalidate method附带六超载里面形成control class of System Windows Forms 名称空间 谢谢 Windows 窗体使用 GDI 进行
  • 托管 C++ 中的泛型泛型

    我想创建一个List of 键值对位于托管 C 项目中 这是我正在使用的语法 List
  • 将异步调用变成同步调用

    将异步调用转变为同步有什么好的实践 模式 吗 我有一个第三方库 它的方法都是异步的 要获得几乎任何方法的结果 您必须侦听事件 这将带来一些上下文 基本上它看起来像 service BeginSomething service OnBegin
  • 用于检查项目文件中的项目变量和引用路径的 api

    我正在研究一个 net application VS2010 与 x 没有 解和变量号这些解决方案中的项目数量 我需要检查项目属性 特定于一定数量的项目 是否同质 并且检查 验证构建期间的参考路径 有没有一个API是这样的吗 如果没有 我该
  • 获取 WPF 控件的所有附加事件处理程序

    我正在开发一个应用程序 在其中动态分配按钮的事件 现在的问题是 我希望获取按钮单击事件的所有事件 因为我希望删除以前的处理程序 我尝试将事件处理程序设置为 null 如下所示 Button Click null 但是我收到了一个无法分配 n

随机推荐