您可以将针对完整框架的软件包导入 ASP.NET Core 3+ 应用程序吗?

Can you import a package targeting full framework into an ASP.NET Core 3+ application?

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

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

我假设您可以引用任何以 netstandard 为目标的包,但是仅以完整框架为目标的包(即仅以 net45 为目标的遗留包)呢?

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

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

发现这些

背景

首先,您 ASP.NET Core 3.x applications can no longer target the .NET Framework, as announced by Microsoft in 2018. That capability previously allowed ASP.NET Core applications to call into .NET Framework libraries 是正确的,因此为迁移到 .NET Core 的 Web 应用程序提供了一个中间解决方案。

Note: Since the .NET Framework only runs on Windows machines, writing ASP.NET Core web applications which targeted the .NET Framework implicitly restricted those applications to running on Windows.

行为

即使以 .NET Core 或现在的 .NET 5 为目标,您仍然可以引用 .NET Framework 包和程序集,前提是您在 Windows 机器上并且拥有相应的 .NET 文件。 NET 框架安装。它的内部工作原理有点复杂,但简而言之,.NET Core 和 .NET 5 将评估 .NET Framework 程序集 ,就像 它们是 .NET Standard assemblies。如果 API 调用是 also 在 .NET Core 运行 时实现的,它将工作正常——但如果 API 调用是 独家 .NET Framework 的一部分,您将收到一个例外。

Surprise! It's really important to emphasize that this is a runtime exception. You will still be able to reference the .NET Framework assembly, write calls to problematic members, and compile your code without any warnings. But as soon as you call into code dependent on a .NET Framework-specific assembly, you'll receive the runtime exception.

例子

在 .NET 3.0 中,.NET Framework 库的重要部分已移植到 .NET Core。事实上,这包括大部分 System.Drawing libraries you referenced as an example—though there are good reasons you may not want to use them. If you dig a bit deeper, however, there are plenty of libraries which remain unsupported. One obvious example is the WebConfigurationManager,可用于从 web.config 文件访问配置设置。

.NET 框架代码

因此,举个例子,假设您在 .NET Framework class 库中有以下函数,returns 来自 web.config<AppSetting>s元素:

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

ASP.NET核心代码

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

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

异常

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

System.TypeLoadException: 'Could not load type 'System.Web.Configuration.WebConfigurationManager' from assembly 'System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'.'

避免意外

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

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

例子

如果您 运行 可移植性分析器在上面的示例代码中,例如,它会 output an Excel spreadsheet 识别 T:System.Web.Configuration.WebConfigurationManager 不支持 例如.NET Core,Version=v3.1.NET Standard + Platform Extensions,Version=v2.0.

Note: Microsoft used to offer an API Analyzer as a NuGet package, which promised to provide design-time analysis in Visual Studio. Unfortunately, the code hasn't been updated in two years, and the latest release is 0.2.12-alpha. In my evaluation, it was not effective at identifying issues.

示例项目

我整理了一个 sample project on GitHub 来演示上述行为。它包括以下项目:

两个 ASP.NET 核心网站都包含两个调用同一个 .NET Framework 4.8 class 库的端点。第一个是“Hello world”示例,它将在两个项目上执行良好,因为它完全依赖于常见的 APIs:

http://localhost:5000/Basic/Index

第二个将在 ASP.NET Core 3.1 项目上失败,因为它调用了遗留 WebConfigurationManager API:

http://localhost:5000/Basic/Configuration

Disclaimer: This is a quick and dirty repository that I put together to verify my understanding prior to posting this. If there's interest, I'll tidy it up and document it. For now, however, it may prove useful for those of you who need to see this in action.

致谢

@Chris Pratt offered 涵盖与去年类似的 material。值得一读。