【问题标题】:Can you import a package targeting full framework into an ASP.NET Core 3+ application?您可以将针对完整框架的包导入 ASP.NET Core 3+ 应用程序吗?
【发布时间】:2020-06-19 06:15:36
【问题描述】:

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

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

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

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

【问题讨论】:

  • 我认为这是不可能的。虽然有端口。例如。 System.Drawing 可以在 nuget 上找到,并安装在 .net 核心项目中。
  • 您可以引用针对 net45 的 nuget 包,但前提是它们使用 .NET Core 3.x 中可用的 API。所以基本上你必须在所需的程序集上运行 .NET 兼容性分析器
  • 如果必须调用 .NET Framework 的别名,请使用“已弃用的框架”而不是“完整的框架”。因为 .NET Framework 不是 .NET Core 的超集,也没有获得任何功能更新。

标签: asp.net-core .net-standard asp.net-core-3.0


【解决方案1】:

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


背景

首先,ASP.NET Core 3.x applications can no longer target the .NET Frameworkannounced by Microsoft in 2018 是正确的。该功能以前为 allowed ASP.NET Core applications to call into .NET Framework libraries,因此为迁移到 .NET Core 的 Web 应用程序提供了中间解决方案。

注意: 由于 .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 assemblies。如果 API 调用在 .NET Core 运行时中实现,它将正常工作 — 但如果 API 调用是 .NET Framework 的一部分,您将收到一个例外。

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

示例

在 .NET 3.0 中,大部分 .NET Framework 库已移植到 .NET Core。事实上,这包括您作为示例引用的大部分System.Drawing 库——尽管有good reasons you may not want to use them。但是,如果您再深入一点,就会发现很多库仍然不受支持。一个明显的例子是WebConfigurationManager,它可以用来访问web.config文件中的配置设置。

.NET 框架代码

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

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

ASP.NET 核心代码

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

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:'无法从程序集'System.Web,Version=4.0.0.0,Culture=neutral,PublicKeyToken=b03f5f7f11d50a3a'加载类型'System.Web.Configuration.WebConfigurationManager'。'

避免意外

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

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

示例

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

注意: Microsoft 曾经提供 API Analyzer 作为 NuGet package,承诺在 Visual Studio 中提供设计时分析。不幸的是,the code 已经两年没有更新了,the latest release is 0.2.12-alpha。在我的评估中,它不能有效地发现问题。

示例项目

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

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

http://localhost:5000/Basic/Index

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

http://localhost:5000/Basic/Configuration

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

致谢

@Chris Pratt 提供了an excellent answer 去年报道了类似的材料。值得一读。

【讨论】:

  • 仅供参考:这个答案在 .NET 5 中仍然适用——并且在即将到来的 .NET 6 中也应该适用。我已经更新了答案以解决这个问题,以及一些特定于 .NET 5 的问题考虑因素,例如引入 Compatibility Analyzers 以警告 .NET 5 本身的平台变化。
猜你喜欢
  • 2019-08-19
  • 2017-04-16
  • 1970-01-01
  • 2018-10-15
  • 1970-01-01
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2015-08-26
相关资源
最近更新 更多