.NET 框架兼容性简介

[原文发表地址]: Introduction to .NET Framework Compatibility

[原文发表时间]: May 2, 2016

 

前言

从.NET框架4.0开始,所有主版本号为4(称为“4.x”版本)的.NET框架,都会进行就地更新。这就意味着在一段时间内,电脑上安装的只有一个.NET 4.x框架。安装.NET 4.5框架将替换.NET 4.0框架,.NET 4.5.1框架将替换.NET 4.5框架,.NET 4.6框架将替换.NET 4.5.1,以此类推。

由于这些就地更新的特点,原本在.NET 4.0框架上运行的应用程序,在电脑安装的.NET框架升级后,可能需要在.NET 4.6上运行。.NET 4.x框架之间的兼容性是非常高的,因此在.NET 4.x框架下正常工作的应用程序,通常也会在较新版本的.NET框架下正常运行。然而不同的.NET 4.x框架会有一些变化,因此应用程序应该在其将运行的任何版本的.NET框架上测试下。

本文概述了最佳做法和工具,用来使支持新的.NET 版本更容易。

 

发生了哪些变化?为什么?

对于.NET 团队来说,和之前版本的.NET框架的兼容性,是一个高优先级的工作。事实上,.NET框架所有的更改都是由经验丰富的工程师进行审核,他们会对这些改变在客户的应用程序上的影响进行评估。

尽管如此,仍然存在兼容性问题。原因之一是,在更新.NET框架时,兼容性并不是唯一的优先事项。有时,由于功能性的原因,不得不进行更改,来解决某个安全漏洞,或者是支持某个行业标准。

还有一些偶然发生的兼容性问题。.NET框架团队会进行全面的兼容性测试,以防止这些问题,但仍然会漏掉一些问题。还有更复杂的情况,修复兼容性问题本身就是一种影响兼容性的改变(因为有些用户可能依赖于这些无意的新行为)。在这样的情况下(解决无意的行为更改),.NET框架团队常常会使用一个称为“quirking”的解决方案。

 

Quirking和目标 .Net框架

Quirking指的是对于缓解兼容性问题,在.NET 框架中有两个单独的代码路径,并且选择一种作为应用程序的目标.NET 框架版本的路径。这种方式缓解了许多.NET 框架兼容性的问题,因为应用程序在较新的.NET框架上运行时,只要在没有变化的目标.NET框架中运行,就避免了很多潜在的问题。Quirking行为是被应用程序的目标.NET框架自动确定,但可以由开发人员使用应用程序或计算机配置设置来进行重写。虽然通过奇想行为减轻了很多兼容性的问题,但是由于安全方面的考虑,以及技术上的限制,并不是所有的兼容性问题都可以被Quirking行为解决。

举一个例子,如果一个目标.NET框架是4.5的应用程序,在安装了.NET 4.5.2的电脑上运行,即使在较新的框架上执行应用程序,为了减少兼容性问题,它也会模拟.NET 4.5的行为。

目前, 微软对 .NET 4.0 4.5 4.5.1已停止支持 ,但是需要特别注意的是,根据新 .NET框架的支持政策, 以那些低版本为目标 .NET框架的应用程序在高版本的 .NET框架上的正常运行,将会继续得到支持。

目标版本是在创建应用程序域 (通常是在托管可执行文件启动时)时,由应用程序的主程序集的目标框架属性决定的。此属性可以通过以下方式设置︰

Quirking设置是 应用程序域 范围。在大多数情况下,类库(dll的)将根据依赖于于它们的可执行文件,而使用或者不使用quirking。正因为如此,即使没有quirking应用,创建者的共享库可能需要确保他们的代码能够正常工作。

 

兼容性开关

除了基于目.NET标框架的自动急转之外,开发人员可以通过设置兼容性开关,明确选择使用或者不使用影响兼容性的变化,手动启用或禁用个别兼容性急转(以及其他一些不是自动急转的行为)。这些“兼容性开关”对于允许开发人员把较新版本的.NET框架作为目标.NET框架(为了使用.NET的新功能)时非常有用,这样仍然可以选择不使用一些已知的会影响应用程序的改动。兼容性开关设置方式有以下几种:

  • 通过配置文件设置
  • 通过环境变量设置
  • 在项目的源代码中以编程方式设置

如何设置兼容性开关的详细信息,虽然没有在这篇介绍性的博客中提到,但在后续的跟进中,会有关于这方面更多深入的细节。

MSDN 上关于兼容性问题的文档中,经常会提到兼容性开关,需要时可以查阅。

 

兼容性问题文档

所有已知的.NET 框架兼容性问题都记录在 MSDN 上。

从.NET 框架 4.5.1 开始,兼容性问题被列为“运行时更改'' 或 “重定向更改”。

  • 运行时更改,指的是影响任意应用程序在较新的.NET 框架版本 (这些变化不是quirking) 上运行的更改。
  • 重定向更改,指的是只影响应用程序重新以较新.NET框架为目标框架生成的更改。这些是.NET 框架变化,或者是编译工具的变化。对于.NET 4.0 和 .NET 4.5 之间的变化,在兼容性问题表的项目里,运行时和重定向的区别并不显示,但可以通过阅读说明来进行区分。

除了 MSDN 上面的文档,.NET 框架兼容性问题都可以作为标记文件 ,是可供使用的兼容性工具(见下文)。可以通过直接读取参考文件 (或在列表的 MSDN 镜像中), 来了解有关兼容性的问题。这个参考文件是开源 GitHub 存储库中的一部分,可以提交请求,或者创建任何需要修正的问题。.NET 团队会将参考文件上面的信息和 MSDN 上的信息进行同步。

 

编译器的兼容性问题

除了上文提到的.NET 框架运行时和重定向的兼容性问题之外,在不能进行急转的C#和VB编辑器版本之间,还有一小部分不会发生在运行时的更改问题。例如,由于C# 4.0 编译器和 5.0 C# 编译器 在生成中间语言时的极小差异,开发人员在新的编辑器中重新编译应用程序的时候,必须留意此类问题。

因为这些兼容性问题仅在新的编译器中重新编译时才会显现,所以它们不会影响到以前编译过的二进制文件在新版本的.NET 框架上运行。为此,MSDN 文档中将这些问题归类为重定向的变化。兼容性问题标记文档会将编译器兼容性问题标记为“编译时”的重定向的更改问题,这种问题和 “quirking “ 重定目标更改有一些差异。

 

问题识别工具

在 GitHub 上发布兼容性问题标记文件的主要目的,是为了兼容性工具的使用。这些工具使得从一个.NET 框架版本到另一个的迁移变得比较容易。现在,我们介绍以下两个兼容性分析工具集。

API移植性分析器

ApiPort (该工具的简称),它能够扫描二进制文件,并标识应用程序接口(以下简称API)使用的所有.NET 框架。然后,它将这些 API和兼容性问题参考文件中存储的数据进行比较,并针对所使用的API提供一份报告,是关于一个.NET框架4.x和另一个版本之间的API的一些更改。命令行选项可以缩小扫描范围 (例如,只考虑指定的.NET 框架版本之间的更改)。完整文档请参阅ApiPort中断更改扫描使用说明。使用ApiPort工具时,需要牢记的注意事项有以下两点:

  1. 因为 ApiPort 只关注API调用的.NET,因此它有可能会发一些误报。大多数.NET 兼容性问题只影响某个API的特定代码路径。简单地使用这些 API,并不意味着应用程序就会受到兼容性问题的影响。通读更改说明,以确定所报告的问题是否有可能在你的特定应用程序中出现。
  2. 因为 ApiPort 只关注API调用的.NET,一些兼容性问题无法通过此工检测出来。例如,当只扫描中间语言时,在 WPF 应用程序中使用已更改的 XAML 控件可能不会被发现。 ApiPort 是一个很有用的工具,但不能替代兼容性测试的。

.NET 框架兼容性分析器

.NET 框架兼容性分析器是一整套Roslyn诊断代码分析器,其使用源代码中的语法树以及语义模型,从而更智能地决定一个项目是否会遇到兼容性问题。他们仍然会存在误报,但相比ApiPort 工具会准确很多。

这些工具可以通过在NuGet.org 网页上搜索 Microsoft.DotNet.FrameworkCompatibilityDiagnostics得到。.NET 框架团队目前正在对这些分析器开放资源码。想要获得更多的在开放资源代码成果的更新,请关注这个博客。

 

报告新的兼容性问题

当把应用程序从一个.NET 框架版本迁移到另一个的时候,你偶尔可能会遇到在 MSDN 或 ApiPort 参考文件中没有记录的兼容性问题。如果这种情况发生,请让我们知道!.NET 团队将会不断地保持兼容性文档最新。

在.NET 框架中,没有文档说明的兼容性问题可以用以下方式报告:

  • 使用 Visual Studio 里面的"发送笑脸"反馈功能来发送详细的变更。
  • 在ApiPort存储库中创建问题来题记录那些还没有被记录在工具的标记文件中的.NET 框架兼容性问题。.NET 的团队 (或社区成员) 将会调查并适当的添加文档和支持。

 

结语

.NET 框架力求与每个新的框架版本高度兼容。尽管如此,一些兼容性问题仍然是不可避免的。了解这些变化,并且知道怎样去缓解这些问题,可以保持你的应用程序在新版本的.NET 框架上成功运行。

本文提及的一些兼容性最佳做法包括:

  • 不是必须的情况,不要重定向为较新版本的.NET框架来作为目标框架。因为这样应用程序可以利用兼容性”quirking”功能,从而使兼容性问题减少到最低限度。
  • 如果你在用来运行你的应用程序的.NET 框架版本上有任何的控件,就使用较新版本的.NET 框架。这是因为.NET4.x上面的许多兼容性问题已经在后续版本中得到了修复。例如,在4.0 至 4.6 之间的兼容性问题就比4.0到4.5之间的兼容性问题少。
  • 如果应用程序是使用较新的编译器重新编译的,就一定要确保进行彻底的测试。这可以暴露编译器兼容性问题 (虽然这些问题很少见)。
  • 使用兼容性工具找出潜在问题,常用的工具有 API 移植性分析器.NET 框架兼容性分析器
  • 在你期望运行的所有.NET 框架版本上,测试你的应用程序。

使用这些技术,应用程序将会继续在新版本的.NET 框架中运行。

 

相关资料