.NET 序列化在不同框架版本之间的稳定性
我正在开发的一个项目需要在关闭之前序列化数据结构,并在再次启动时从该序列化数据恢复其状态。
去年,我们正在为 .NET 1.1 进行构建,并遇到了一个棘手的问题,
- 我们的代码在 .NET 2.0 上运行,
- 客户使用某些软件进行升级,该软件以某种方式将 1.1 设置为默认值,
- 我们的代码在 .NET 1.1 上运行,并且无法反序列化其存储状态
这个特定问题已通过禁止特定软件升级而“解决”,并且现在不应该成为问题,因为我们的目标是 .NET 2.0 框架(因此我们不可能在 1.1 上运行)。
这种序列化在 2.0 和更新的框架之间再次发生不兼容变化的可能性有多大? 如果我们使用
将代码修复为 2.0.50727,那么 2.0.50727.1434 和 2.0.50727.nnnn(未来的某个版本)之间发生更改的可能性有多大? 被序列化的数据结构是来自标准类库的数组、映射、字符串等。
此外,即使在进一步升级 .NET 后,是否也能保证始终安装 2.0.50727 框架? 欢迎指向 Microsoft 文档。
A project I'm working on requires serializing a data structure before shutting down and restores its state from this serialized data when it start up again.
Last year, we were building for .NET 1.1, and ran into a tricky issue where
- our code ran on .NET 2.0
- a customer upgraded with some software that somehow set 1.1 as default
- our code ran on .NET 1.1 and was unable to deserialize its stored state
This particular issue was "resolved" by barring that particular software upgrade, and shouldn't be a problem now that we're targeting the .NET 2.0 framework (so we can't possibly run on 1.1).
What is the chance that this serialization could again change incompatibly between, 2.0 and newer frameworks? If we use <supportedVersion>
to fix our code to 2.0.50727, what are the chances of changes between 2.0.50727.1434 and 2.0.50727.nnnn (some future release)? The data structures being serialized are arrays, maps, strings, et cetera from the standard class libraries.
Additionally, is it guaranteed that a 2.0.50727 framework will be always installed even after further .NET upgrades? Pointers to Microsoft documentation welcome.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
框架版本之间发生变化的可能性很低(但不是零!)。 目的是您应该能够使用二进制序列化和远程处理在运行不同框架版本的客户端和服务器之间进行通信。 .NET 1.x 和 2.0 之间的不兼容性是一个错误 有可用的补丁。
然而,二进制序列化还有其他问题,特别是对正在序列化的结构的版本控制的支持很差。 从您描述的用例来看,Xml 序列化是显而易见的选择:如果您不介意对 .NET 3.x 的依赖,DataContractSerializer 比 XmlSerializer 更灵活。
您无法保证 .NET Framework 2.0 将始终安装在未来版本的 Windows 上。 但我确信 Microsoft 将努力确保大多数 .NET 2.0 应用程序在 .NET 4.x 及更高版本上运行不变。 我对此没有任何参考:任何此类承诺在任何情况下都仅真正适用于下一版本的 Windows (Windows 7)。
The chances are low (but not zero!) that there will be changes between framework versions. The intention would be that you should be able to use binary serialization and remoting to communicate between a client and a server running different framework versions. The incompatibility between .NET 1.x and 2.0 is a bug for which a patch is available.
However binary serialization has other issues, especially poor support for versioning of the structure you're serializing. From the use case you've described, Xml serialization is the obvious choice: DataContractSerializer being more flexible than XmlSerializer if you don't mind the dependency on .NET 3.x.
You can't guarantee that the .NET framework 2.0 will always be installed on future versions of Windows. But I'm sure Microsoft will work hard to ensure that most .NET 2.0 apps will run unchanged on .NET 4.x and later versions. I don't have any references for this: any such commitment would in any case only really apply to the next version of Windows (Windows 7).
经验法则通常是:XML 序列化应该能够在新的框架版本中生存,因此可以长期存储,但二进制序列化不能(因此只能是暂时的)。
The rule of thumb is generally: XML serialization should be able to survive new framework versions and therefore can be stored long-term, but binary serialization cannot (and therefore should only ever be transient).
你使用什么序列化器? 在许多方面,像 XmlSerializer 或 DataContractSerializer 这样的序列化器可以缓冲许多细节,并提供更简单的可扩展性选项。
在某些时候,新的 CLR 版本无疑是必要的 - 所以我认为没有人可以对 2.0.50727 做出任何保证; 不过,短期内你应该是安全的。 我希望减少重大更改...
[更新了另一个回复的注释]
如果您出于空间/性能原因需要二进制格式,那么另一个选择是使用不同的二进制序列化器。 例如,protobuf-net 适用于所有 .NET 变体*,但二进制文件格式(由 Google 制定)是跨平台兼容的(Java、C++ 等)——使其非常便携、快速且小巧。
*=我还没有在微框架上尝试过,但是CF、Silverlight、Mono、.NET 2.0等都支持。
What serializer are you using? In many ways, a serializer like XmlSerializer or DataContractSerializer buffers you from many details, and provides simpler extensibility options.
At some point, a new CLR version will undoubtably be necessary - so I don't think anybody can make any guarantees about 2.0.50727; you should be safe short-term, though. And I would hope for fewer breaking changes...
[updated following note on another reply]
If you want a binary format for space/performance reasons, then another option is to use a different binary serializer. For example, protobuf-net works on all .NET variants*, but the binary format (dvised by Google) is cross-platform compatible (Java, C++, etc) - making it very portable, quick, and small.
*=I haven't tried it on micro framework, but CF, Silverlight, Mono, .NET 2.0 etc are all supported.
如果兼容性是一个问题,ISerialized界面可能是您正在寻找的解决方案。 此界面使您可以更好地控制项目的序列化方式。 有关详细信息,请尝试这篇 msdn 上的文章。
If compatibility is a concern, the ISerializable interface might be the cure you're looking for. This interface gives you more control over how items are serialized. For more info try this article on msdn.
我有两件事要添加到其他答案中......
首先,使用自定义 SerializationBinder 可以帮助您解决导入遗留序列化数据的许多困难。
其次,我认为必须为任何持久数据编写广泛的单元测试。 我总是特别做两个测试:
I have two things to add to the other answers...
First, making use of a custom SerializationBinder can get you round lots of difficulties importing legacy serialized data.
Second, I consider it mandatory to write extensive unit tests for any persisted data. I always do two tests in particular:
理论上,XML 应该始终可以在不同版本的 .NET Framework/.NET Core/.NET 之间移植。 但规则总有例外。
例如,如果您以 XML 格式移动
System.Data.DataTable
,并且如果其中一些数据表包含System.Guid
类型的列,那么您'很可能会带来惊喜! 请考虑以下示例代码:与大多数其他系统类型不同,
System.Guid
获取列定义中包含的特定于版本的msdata:DataType
属性,并且会抛出System.InvalidOperationException:当不兼容的运行时尝试反序列化列时,包装
中存在错误。System.ArgumentException:列需要有效的 DataType
的 XML 文档 (.., ...).NET Framework 4.7.2 输出:
.NET Core 3.1 输出:(是的,它输出版本 4.0.0.0)
.NET 5 输出:
.NET 6 输出:
.NET 7 输出:
In theory XML should always be portable between different versions of .NET Framework/.NET Core/.NET. But there are always exceptions to the rule.
For example IF you're moving
System.Data.DataTable
s around in XML format, and IF some of those data tables contain columns of typeSystem.Guid
, then you're likely in for a surprise! Consider the following example code:Unlike most other system types
System.Guid
gets a version-specificmsdata:DataType
attribute included in the column definition and that will throw aSystem.InvalidOperationException: There is an error in XML document (.., ...)
wrapping aSystem.ArgumentException: Column requires a valid DataType
when an incompatible runtime attempts to deserialize it..NET Framework 4.7.2 output:
.NET Core 3.1 output: (yes, it outputs version 4.0.0.0)
.NET 5 output:
.NET 6 output:
.NET 7 output:
您不必使用 XML 即可获得更高的灵活性和版本控制。
我使用了 Simon Hewitt 的开源库,请参阅优化.NET 中的序列化 - 第 2 部分,而不是默认的 .NET 序列化。 它提供了一些自动化功能,但本质上您可以控制序列化和反序列化的信息流。 对于版本控制,可以首先序列化(文件)版本
反序列化时间以及解释信息流的方式取决于版本。
做起来很简单,尽管由于明确的原因而有些乏味
序列化/反序列化。
作为奖励,它的速度提高了 20-40 倍,并且对于大型数据集占用的空间更少(但对于您的情况来说可能并不重要)。
You do not have to use XML in order to gain higher flexibility and versioning.
I have used Simon Hewitt's open source library, see Optimizing Serialization in .NET - part 2 instead of default .NET serialisation. It offers some automation, but essentially you can control the stream of information that is serialised and deserialised. For versioning the (file) version can be serialised first and at
deserialisation time the way the stream of information is interpreted is dependent on the version.
It is quite simple to do, although somewhat tedious due to the explicit
serialisation / deserialisation.
As a bonus it is 20-40 times faster and takes up less space for large data sets (but may be unimportant in your case).