库是不是应该明确针对 .NET Core 3?
Posted
技术标签:
【中文标题】库是不是应该明确针对 .NET Core 3?【英文标题】:Should a library explicitly target .NET Core 3?库是否应该明确针对 .NET Core 3? 【发布时间】:2020-01-10 18:10:39 【问题描述】:随着 .NET Standard 2.0 的发布,建议以 .NET Standard 2.0 为目标,即使您已经以 1.x 为目标。
https://docs.microsoft.com/en-us/dotnet/standard/net-standard:
但是,针对较低的 .NET Standard 版本会引入许多支持依赖项。如果您的项目以 .NET Standard 1.x 为目标,我们建议您也以 .NET Standard 2.0 为目标。这简化了在 .NET Standard 2.0 兼容框架上运行的库用户的依赖关系图,并减少了他们需要下载的包数量。
现在另一个重大变化即将来临! .NET Core 3,我看到 Microsoft也 正在将 .NET Core 3 用于 Microsoft 软件包。
例如,Microsoft.Extensions.Logging 的目标是 .NET Standard 2.0 和 .NET Core 3 (.NETCoreApp 3.0):
我比较了 XML 文件,两个 API 看起来一样(可能不是比较它们的最佳方法)
现在的问题;)
作为依赖于 Microsoft.Extensions.Logging 并试图支持 .NET Core 3 的库维护者: 如果我不需要 .NET Core 3 的特定内容,我是否也应该以 .NET Core 3 为目标 - 还是仅 .NET Standard 2.0 就足够了?
【问题讨论】:
【参考方案1】:简答
如果您不想使用 .NET Core 3 中的任何内容,或者不想提供任何 .NET Core 3 优化,则不必以 .NET Core 3 为目标。另一方面,双重定位不会花费您任何成本,并且可能允许您摆脱现在内置于 .NET Core 3 中的库引用。至少您可以摆脱现在的一些库引用运行时附带。
长答案
这完全取决于你在做什么,你想做什么。库必须以 .NET Core 3.0 为目标,因为它的依赖项将其包含在目标中。
例如,the source code 表明 Microsoft.Extensions.Logging
似乎没有任何 C# 8/.NET Core 3.0 特定代码。它以 3.0 为目标,因为它是那一波扩展的一部分,因此双重目标不需要任何修改。
另一方面,Config.Json 不必引用 System.Text.Json
和 System.Threading.Tasks.Extensions
,因为它们是运行时的一部分。
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0'">
<Reference Include="System.Text.Json" />
<Reference Include="System.Threading.Tasks.Extensions" />
</ItemGroup>
其他好处
对于维护者,.NET Core 3.0/.NET Standard 2.1 提供了许多 健全的功能,例如:
可为空的引用类型。您将在自己的代码中避免大量 NRE。您可能还会发现很多隐藏的错误。 默认接口成员。当您将新成员添加到公共界面时,您不必担心会破坏用户的代码。 IAsyncEnumerable。无需再等待一堆异步操作的所有结果 switch 表达式和更强大的模式匹配和解构语法。对于其中一些功能,您只能添加一些仅适用于 .NET Core 的方法。例如,ChannelReader class 在部分文件中添加单个 ReadAllAsync()
方法,该方法从通道读取项目并返回 IAsyncEnumerable<>
,例如:
public virtual async IAsyncEnumerable<T> ReadAllAsync([EnumeratorCancellation] CancellationToken cancellationToken = default)
while (await WaitToReadAsync(cancellationToken).ConfigureAwait(false))
while (TryRead(out T item))
yield return item;
这是一个小但非常方便的补充。它允许您通过以下方式接收消息:
await foreach(var msg from reader.ReadAllAsync())
....
另一方面,NRT 甚至对 .NET Standard 2.0 也有帮助,因为它们可以帮助您在为 .NET Core 3.0 编译时捕获源代码中的可空性错误。
【讨论】:
但好处不是我还需要针对旧平台吗?我假设我不能将 c#8 语法用于(也针对).net 标准 2.0 @Julian 我发布了一个你如何可以的例子。在任何情况下,如果您不想要以 .NET Core 3 为目标,则不必这样做。 Logging 库不会强迫您这样做 好的。但不幸的是,这并不能回答我的问题 @Julian 问题是什么,您希望答案是什么样的?即使您的依赖项之一将其包含在其目标中,您也没有必须以 .NET Core 3 为目标。如果您不想要 .NET Core 3 中的任何内容,则不需要 定位它【参考方案2】:当有人安装包时,NuGet 会使用 TFM 中与项目的 TFM 最匹配的资产。它也对传递依赖项执行此操作。
例如 - 如果项目目标 netcore30 和包 A 在 lib/netcore30 和 lib/netstandard20 下有资产,则 nuget 将选择 lib/netcore30。假设包 A 依赖于 B,包 B 有 netstandard20、net472 的资产,nuget 将选择 netstandard20。
底线是,nuget 将为图中的每个包选择最佳匹配资产。因此,作为库维护者,您无需添加两个 TFM 即可支持 netcore30。您可以定位 netstandard21,这意味着基于此文档 https://docs.microsoft.com/en-us/dotnet/standard/net-standard
支持 netcore30【讨论】:
不幸的是,这无法回答为什么 Microsoft.Extensions.Logging 以 netstandard2.0 + netcore3.0 为目标以及依赖库应该做什么。 @Julian 一个依赖库没有有支持.NET Core 3,如果它不想的话。使用 Microsoft.Extensions.Logging 在 .NET Core 2.1 或 .NET Framework 4.8 中构建应用程序的人每次升级包时都会获得最新的 NuGet 包,而无需切换到 .NET Core 3 恐怕这不能回答我的问题。【参考方案3】:作为依赖于的库维护者 Microsoft.Extensions.Logging,试图支持 .NET Core 3: 我是否也应该以 .NET Core 3 为目标 - 还是只是 .NET Standard 2.0 好 如果我不需要 .NET Core 3 的特定内容就足够了吗?
只要您的所有依赖项都以 .NET Standard 2.0 为目标,包括 Microsoft.Extensions.Logging
,在您的库中定位 .NET Standard 2.0 就足够了。
作为Panagiotis Kanavos said,将 .NET Core 3.0 定位为库的使用者可能会带来好处,因此,如果是这种情况并且不会花费太多,那么请务必将 .NET Core 3.0 定位到.NET Standard 2.0 的补充。
作为karann said,nuget 将始终为图中的每个包选择最佳匹配资产。即
应用 A 使用您的库并以 .NET Core 3.0 为目标。您的库仅面向 .NET Standard 2.0。 NuGet 将使用它,这很好。 应用 A 使用您的库并以 .NET Core 3.0 为目标。您的库同时面向 .NET Standard 2.0 和 .NET Core 3.0。 NuGet 将选择 .NET Core 3.0【讨论】:
有什么理由定位.NET Core 3.0
而不是.NET Standard 2.1
?以上是关于库是不是应该明确针对 .NET Core 3?的主要内容,如果未能解决你的问题,请参考以下文章
使用ASP.NET Core 3.x 构建 RESTful API P11 P12 ActionResult of T 以及 AutoMapper.md
插件项目必须是.NET 3.5 其余代码库是.NET 4.0 怎么解决?
.NET Standard / Core 中的 .vspscc 文件