本文概述了将代码从 .NET Framework 移植到 .NET(以前命名为 .NET Core)时应考虑的事项。 对于许多项目,从 .NET Framework 移植到 .NET 相对简单。 项目的复杂性决定了在初始迁移项目文件后需要执行多少工作。
.NET 中提供应用模型的项目(如库、控制台应用和桌面应用)通常需要很少更改。 需要新应用模型(例如 从 ASP.NET 迁移到 ASP.NET Core)的项目需要更多工作。 旧应用模型中的许多模式具有可在转换期间使用的等效项。
Windows 桌面技术
为 .NET Framework 创建的许多应用程序都使用桌面技术,如 Windows 窗体或 Windows Presentation Foundation (WPF)。 Windows 窗体和 WPF 在 .NET 中都可用,但它们仍然是仅限 Windows 的技术。
在迁移 Windows 窗体或 WPF 应用程序之前,请考虑以下依赖项:
- .NET 的项目文件使用的格式与 .NET Framework 不同。
- 你的项目可能会使用 .NET 中不可用的 API。
- 第三方控件和库可能尚未移植到 .NET,并且仅可用于 .NET Framework。
- 项目使用 .NET 中不再可用的技术 。
.NET 使用 Windows 窗体和 WPF 的开源版本,并包括对 .NET Framework 的增强功能。
有关将桌面应用程序迁移到 .NET 的教程,请参阅以下文章之一:
特定于 Windows 的 API
应用程序在 .NET 支持的平台上仍然可以使用 P/Invoke 调用本地库。 这项技术不限于 Windows。 但是,如果引用的库特定于 Windows,例如 user32.dll 或 kernel32.dll,则代码仅适用于 Windows。 对于希望应用运行的每个平台,必须查找特定于平台的版本,或使代码通用足以在所有平台上运行。
将应用程序从 .NET Framework 移植到 .NET 时,应用程序可能使用了 .NET Framework 提供的库。 许多 .NET Framework 中提供的 API 不会移植到 .NET,因为它们依赖于特定于 Windows 的技术,例如 Windows 注册表或 GDI+ 绘图模型。
Windows 兼容性包向 .NET 提供了大部分 .NET Framework API 图面,并通过 Microsoft.Windows.Compatibility NuGet 包提供。
有关详细信息,请参阅 使用 Windows 兼容性包将代码移植到 .NET。
.NET Framework 兼容性模式
.NET Framework 兼容性模式是在 .NET Standard 2.0 中引入的。 兼容性模式允许 .NET Standard 和 .NET 项目无缝引用 .NET Framework 库,就像这些库是为项目的目标框架编译的一样。 但是,某些 .NET 实现可能支持比其他 .NET Framework 更大的区块。 例如,.NET Core 3.0 将 .NET Framework 兼容性模式扩展到 Windows 窗体和 WPF。 引用 .NET Framework 库不适用于所有项目,例如当库使用 WPF API 时,但它确实能解决许多移植方案的问题。 有关详细信息,请参阅 “分析依赖项”,将代码从 .NET Framework 移植到 .NET。
引用 .NET Framework 库在所有情况下都不起作用,因为它取决于使用哪些 .NET Framework API,以及项目的目标框架是否支持这些 API。 此外,某些 .NET Framework API 仅适用于 Windows。 .NET Framework 兼容性模式会取消阻止许多移植方案,但你应该测试项目以确保它们也可以在运行时工作。 有关详细信息,请参阅 分析依赖项以将代码从 .NET Framework 移植到目标平台。
SDK 风格项目中的目标框架变更
如前所述,.NET 的项目文件使用的格式与 .NET Framework 不同,称为 SDK 样式的项目格式。 即使未从 .NET Framework 移动到 .NET,仍应将项目文件升级到最新格式。 指定目标框架的方式在 SDK 样式项目中有所不同。 在 .NET Framework 中,该 <TargetFrameworkVersion>
属性与用于指定 .NET Framework 版本的标识符一起使用。 例如,.NET Framework 4.7.2 如以下代码片段所示:
<PropertyGroup>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
</PropertyGroup>
SDK 样式项目使用不同的属性来标识目标框架(该 <TargetFramework>
属性)。 面向 .NET Framework 时,名字对象以 net
开头,并以不带任何句点的.NET Framework 版本结束。 例如,net472
是 .NET Framework 4.7.2 的标识符:
<PropertyGroup>
<TargetFramework>net472</TargetFramework>
</PropertyGroup>
有关所有目标名称的列表,请参阅 SDK 风格项目中的目标框架。
不可用的技术
.NET Framework 中的一些技术在 .NET 中不存在:
-
不支持创建其他应用程序域。 对于代码隔离,请使用单独的进程或容器作为替代方法。
-
远程处理用于跨不再受支持的应用程序域进行通信。 对于简单的跨进程通信,可将进程间通信 (IPC) 机制视为远程处理的备用方案,如 System.IO.Pipes 类或 MemoryMappedFile 类。 对于更复杂的方案,请考虑 使用 StreamJsonRpc 或 ASP.NET Core 等框架(使用 gRPC 或 RESTful Web API 服务)。
由于不支持远程处理,因此对委托对象进行
BeginInvoke()
调用和EndInvoke()
调用时将引发PlatformNotSupportedException
。 -
CAS 是 .NET Framework 支持的沙盒技术,但在 .NET Framework 4.0 中已弃用。 它被安全透明度所取代,在 .NET 中不受支持。 而是使用操作系统提供的安全边界,例如虚拟化、容器或用户帐户。
-
与 CAS 类似,不再建议对 .NET Framework 应用程序使用安全透明度沙盒技术,在 .NET 中不受支持。 改用操作系统提供的安全边界,例如虚拟化、容器或用户帐户。
-
System.EnterpriseServices .NET 不支持 (COM+)。
Windows Workflow Foundation (WF)
.NET 不支持 WF。 有关替代方法,请参阅 CoreWF。
有关这些不受支持的技术的详细信息,请参阅 .NET 6+ 上不可用的 .NET Framework 技术。
跨平台
.NET(以前称为 .NET Core)设计为跨平台。 如果代码不依赖于特定于 Windows 的技术,则可以在其他平台上运行,例如 macOS、Linux 和 Android。 此类代码包括项目类型,例如:
- 图书馆
- 基于控制台的工具
- 自动化
- ASP.NET 网站
.NET Framework 是仅限 Windows 的组件。 当代码使用特定于 Windows 的技术或 API(如 Windows 窗体和 WPF)时,该代码仍然可以在 .NET 上运行,但无法在其他操作系统上运行。
库或基于控制台的应用程序可以跨平台使用,而无需更改太多。 移植到 .NET 时,可能需要考虑到这一点,并在其他平台上测试应用程序。
.NET Standard 的未来
.NET Standard 是适用于多个 .NET 实现的 .NET API 的正式规范。 .NET Standard 背后的动机是在 .NET 生态系统中建立更大的统一性。 从 .NET 5 开始,已采用不同的建立统一性方法,这种新方法消除了在许多方案中对 .NET Standard 的需求。 有关详细信息,请参阅 .NET 5+ 和 .NET Standard。
.NET Standard 2.0 是支持 .NET Framework 的最后一个版本。
用于协助移植的工具
可以使用不同的工具来帮助自动化迁移的某些方面,而不是手动将应用程序从 .NET Framework 移植到 .NET。 移植复杂项目本身就是一个复杂的过程。 这些工具可能有助于这一旅程。
即使使用工具来帮助移植应用程序,也应查看本文中 移植部分时的注意事项 。
.NET 升级助手
.NET 升级助手是可在不同类型的 .NET Framework 应用上运行的命令行工具。 它旨在帮助将 .NET Framework 应用升级到 .NET。 运行该工具后, 在大多数情况下,应用将需要更多精力来完成迁移。 该工具包括有助于完成迁移的分析器安装。 此工具适用于以下类型的 .NET Framework 应用程序:
- Windows 窗体
- WPF(Windows Presentation Foundation)
- ASP.NET MVC
- 控制台
- 类库
此工具使用本文中列出的其他工具,例如 try-convert,并指导迁移过程。 有关该工具的详细信息,请参阅 .NET 升级助手概述。
try-convert
该工具 try-convert
是一个 .NET 全局工具,可将项目或整个解决方案转换为 .NET SDK,包括将桌面应用移动到 .NET。 但是,如果项目具有复杂的生成过程(如自定义任务、目标或导入),则不建议使用此工具。
有关详细信息,请参阅 try-convert
GitHub 存储库。
平台兼容性分析器
平台兼容性分析器分析你是否正在使用会在运行时引发PlatformNotSupportedException的API。 尽管如果要从 .NET Framework 4.7.2 或更高版本移动,则很难找到其中一个 API,但最好进行检查。 有关在 .NET 上引发异常的 API 的详细信息,请参阅 始终在 .NET Core 上引发异常的 API。
有关详细信息,请参阅 平台兼容性分析器。
移植时的注意事项
将应用程序移植到 .NET 时,请考虑以下建议:
✔️ 请考虑使用 .NET 升级助手 迁移项目。 尽管此工具为预览版,但它会自动执行本文中详述的大部分手动步骤,并为你提供了继续迁移路径的绝佳起点。
✔️ 请考虑先检查依赖项。 依赖项必须面向 .NET、.NET Standard 或 .NET Core。
✔️ 请从 NuGet packages.config 文件迁移到项目文件中的 PackageReference 设置。 使用 Visual Studio 转换 package.config 文件。
✔️ 考虑升级到最新的项目文件格式,即使你尚未移植应用。 .NET Framework 项目使用过时的项目格式。 尽管为 .NET Core 及更高版本创建了最新的项目格式(称为 SDK 样式项目),但该格式也适用于 .NET Framework。 让项目文件采用最新格式,为将来移植应用提供了良好的基础。
✔️ 请将 .NET Framework 项目重新定位到至少 .NET Framework 4.7.2。 这可确保在 .NET Standard 不支持现有 API 的情况下提供最新的 API 替代项。
✔️ 请考虑使用 .NET 8,这是一个长期支持 (LTS) 版本。
✔️ 请定位 Windows 窗体和 WPF 项目到 .NET 6+ 。 .NET 6 及更高版本包含桌面应用的许多改进。
✔️ 如果要迁移一个库,该库可能还与 .NET Framework 项目一起使用,请考虑以 .NET Standard 2.0 为目标。 您还可以对您的库进行多重目标设计,以同时支持 .NET Framework 和 .NET Standard。
✔️ 如果迁移后收到缺少 API 的错误,请添加对 Microsoft.Windows.Compatibility NuGet 包 的引用。 .NET Framework API 图面的大部分内容可通过 NuGet 包提供给 .NET。