您能否将面向完整框架的包导入到 ASP.NET Core 3+ 应用程序中?

kim*_*gro 3 asp.net-core .net-standard asp.net-core-3.0

我的理解是,从 ASP.NET Core 3.0 开始,.NET Framework 是不受支持的目标框架,因此您只能在 .NET Core 运行时上运行。

如果是这种情况,哪些 NuGet 包可以导入到 ASP.NET Core 3 应用程序中?

我假设您可以引用任何针对 的包netstandard,但是仅针对完整框架的包(即,仅针对 的旧包net45)呢?

如果您导入的包引用了一个不属于 .NET Core 的程序集,即,会发生System.Drawing什么?

Jer*_*ney 7

TL;DR:您仍然可以从 .NET Core 3 甚至 .NET 5 引用(依赖的包).NET Framework 程序集,但是如果您调用任何不依赖于 API 或库的代码,您将收到运行时错误(还)受 .NET Core 支持。您可以使用 Microsoft 的.NET Portability Analyzer发现这些


背景

首先,正如微软在 2018 年宣布的那样,ASP.NET Core 3.x 应用程序不能再以 .NET Framework目标是正确的。该功能以前允许 ASP.NET Core 应用程序调用 .NET Framework 库,因此为 Web 应用程序迁移到 .NET Core 提供了中间解决方案。

注意:由于 .NET Framework 仅在 Windows 计算机上运行,​​因此编写针对 .NET Framework 的 ASP.NET Core Web 应用程序会隐式限制这些应用程序在 Windows 上运行。

行为

但是,即使面向 .NET Core 或现在的 .NET 5,您仍然可以引用 .NET Framework 包和程序集,假设您使用的是 Windows 计算机并安装了相应的 .NET Framework。它的内部工作有点复杂,但缺点是.NET Core 和 .NET 5 将评估 .NET Framework 程序集,就好像它们是.NET Standard 程序集一样。如果API调用也是在.NET核心运行时实现的,它会正常工作,但如果API调用是专门.NET Framework的一部分,您会收到异常。

惊喜!强调这是一个运行时异常非常重要。您仍然可以引用 .NET Framework 程序集、编写对有问题成员的调用以及编译您的代码而不会出现任何警告。但是,只要您调用依赖于 .NET Framework 特定程序集的代码,您就会收到运行时异常。

例子

在 .NET 3.0 中,.NET Framework 库的很大一部分已移植到 .NET Core。事实上,这包括System.Drawing您作为示例引用的大多数库——尽管您可能充分的理由不想使用它们。但是,如果您深入研究一下,就会发现许多库仍然不受支持。一个明显的例子是WebConfigurationManager,它可用于从web.config文件访问配置设置。

.NET 框架代码

因此,举个例子,假设您在 .NET Framework 类库中有以下函数,它从您web.config<AppSetting>s 元素返回一个键数组:

public static class Configuration
{
    public static string[] GetAppSettings() => System.Web.Configuration.WebConfigurationManager.AppSettings.AllKeys;
}
Run Code Online (Sandbox Code Playgroud)

ASP.NET 核心代码

然后,在 ASP.NET Core 控制器中,公开一个端点来检索此数据:

public class MyController: Controller 
{
    public IActionResult ApplicationKeys() => Content(String.Join(", ", Configuration.GetAppSettings()));
}
Run Code Online (Sandbox Code Playgroud)

例外

在面向 .NET Framework 的 ASP.NET Core 2.x 应用程序中,这将正常工作。但是,在 ASP.NET Core 3.x 或 ASP.NET Core 5 应用程序中,调用/My/ApplicationKeys/路由时会收到以下运行时错误:

System.TypeLoadException: '无法从程序集'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'加载类型'System.Web.Configuration.WebConfigurationManager'。'

避免意外

如果你和我一样,这会让你非常紧张。当您尝试调用依赖于不受支持的代码的库时,您更愿意收到设计时错误——或者至少是编译时警告。幸运的是,Microsoft 提供了一个.NET Portability Analyzer,它也可以作为 Visual Studio Extension 使用,正是为了这个目的。

从 .NET 5 开始,SDK 中还内置了一个兼容性分析器,可以识别特定平台上 .NET 5 运行时不支持的调用。这要求目标库使用[SupportedOSPlatform()]属性显式注释其类型,因此您不会收到有关旧版 .NET Framework 类型的任何警告。但这将有助于识别针对各种平台的库的类似兼容性问题。

例子

如果在上面的示例代码运行可移植性分析器,例如,它会输出一个Excel电子表格识别T:System.Web.Configuration.WebConfigurationManager不支持在例如.NET Core,Version=v3.1.NET Standard + Platform Extensions,Version=v2.0

注:微软用来提供一个API分析仪作为NuGet包,其承诺将在Visual Studio提供设计时分析。不幸的是,代码已经两年没有更新了,最新版本是 0.2.12-alpha。在我的评估中,它不能有效地识别问题。

示例项目

在 GitHub 上整理了一个示例项目,它演示了上述行为。它包括以下项目:

两个 ASP.NET Core 网站都包含两个调用同一个 .NET Framework 4.8 类库的端点。第一个是“Hello world”示例,它可以在两个项目上正常执行,因为它完全依赖于通用 API:

http://localhost:5000/Basic/Index
Run Code Online (Sandbox Code Playgroud)

第二个将在 ASP.NET Core 3.1 项目上失败,因为它调用了旧WebConfigurationManagerAPI:

http://localhost:5000/Basic/Configuration
Run Code Online (Sandbox Code Playgroud)

免责声明:这是一个快速而肮脏的存储库,我在发布之前将其放在一起以验证我的理解。如果有兴趣,我会整理并记录下来。然而,就目前而言,它可能对那些需要看到这一点的人有用。

致谢

@Chris Pratt去年提供了一个很好的答案,涵盖了类似的材料。值得一读。


归档时间:

查看次数:

1335 次

最近记录:

4 年,6 月 前