假设我有一个我想要定位netstandard1.3的类库,但也使用BigInteger
。这是一个简单的例子 - 唯一的源文件是Adder.cs
:
using System;
using System.Numerics;
namespace Calculator
{
public class Adder
{
public static BigInteger Add(int x, int y)
=> new BigInteger(x) + new BigInteger(y);
}
}
回到project.json
的世界,我会在netstandard1.3
部分中定位frameworks
,并明确依赖System.Runtime.Numerics
,例如版本4.0.1。我创建的nuget包将列出该依赖项。
在基于csproj的dotnet工具的勇敢新世界中(我使用命令行工具的v1.0.1),在定位时,implicit metapackage package reference到NETStandard.Library 1.6.1
netstandard1.3
。这意味着我的项目文件非常小,因为它不需要显式依赖:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>
</Project>
...但是生成的nuget包依赖于NETStandard.Library
,这表明为了使用我的小型库,你需要所有。
事实证明我可以使用DisableImplicitFrameworkReferences
禁用该功能,然后再次手动添加依赖项:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Numerics" Version="4.0.1" />
</ItemGroup>
</Project>
现在我的NuGet软件包确切地说明了它的依赖性。直观地说,这感觉像是一个更精简的&#34;封装
那么我图书馆的消费者的确切区别是什么?如果有人试图在UWP应用程序中使用它,那么第二个,&#34;修剪&#34;依赖形式意味着生成的应用程序会更小?
通过不清楚地记录DisableImplicitFrameworkReferences
(据我所见;我读到它in an issue)并在创建项目时将隐式依赖作为默认值,Microsoft是鼓励用户只依赖于元数据包 - 但是当我制作类库包时,我怎么能确定它没有缺点?
答案 0 :(得分:75)
过去,我们已经向开发人员提出了不参考元的建议
来自NuGet包的包(NETStandard.Library
),而是引用
单个包,例如System.Runtime
和System.Collections
。该
理由是我们认为元包是一堆的简写
这些包是.NET平台的实际原子构建块。该
假设是:我们最终可能会创建另一个.NET平台
支持其中一些原子块,但不是全部。因此,您引用的包越少,您的便携性就越高。还有人担心我们的工具如何处理大包图。
继续前进,我们将简化这一点:
.NET Standard是一个原子构建块。换句话说,新平台 不允许将.NET标准化 - 他们必须实现所有这些。
我们正在不再使用套餐来描述我们的平台, 包括.NET Standard。
这意味着,您不必为.NET Standard引用任何NuGet包 了。你表达了你对lib文件夹的依赖,这正是如何 它适用于所有其他.NET平台,特别是.NET Framework。
但是,现在我们的工具仍将在参考中燃烧
NETStandard.Library
。也没有任何伤害,它只会变成
多余的前进。
我将更新.NET Standard repo上的FAQ以包含此问题。
更新:此问题现在为part of the FAQ。
答案 1 :(得分:18)
团队过去常常建议弄清楚最薄的包裹是什么。他们不再这样做了,建议人们只需引入NETStandard.Library(在SDK风格的项目中,这将自动完成)。
我从来没有得到一个完全直截了当的答案,为什么那样,所以请允许我做一些有根据的猜测。
主要原因可能是它允许它们隐藏依赖库的版本差异,否则在更改目标框架时需要跟踪自己。它也是一个更加用户友好的系统与基于SDK的项目文件,因为你坦率地不需要任何引用来获得一个相当大的平台块(就像你曾经使用Desktop-land中的默认引用,尤其是mscorlib )。
通过将netstandard
库或netcoreapp
应用程序的元定义推送到适当的NuGet包中,他们不必在定义中构建任何特殊知识这些东西就像Visual Studio(或dotnet new
)看到的那样。
在发布期间可以使用静态分析来限制运送的DLL,这是他们在为UWP进行本机编译时所做的事情(虽然有一些警告)。他们今天没有为.NET Core做到这一点,但我认为这是他们考虑的优化(以及支持本机代码)。
如果您愿意,没有什么可以阻止您做出选择性的事情。我相信你会发现你几乎是唯一一个这样做的人,这也违背了目的(因为假设每个人都带来NETStandard.Library
或Microsoft.NETCore.App
)。
答案 2 :(得分:8)
您不应该禁用隐式引用。库将能够运行的所有平台都已具有NETStandard.Library
依赖项所需的程序集。
.NET标准库是一个规范,您编译的一组引用程序集提供了一组API,这些API保证存在于一组已知的平台和平台版本上,例如.NET Core或.NET Framework。它不是这些程序集的实现,只是足够的API形状,以允许编译器成功构建您的代码。
这些API的实现由目标平台提供,例如.NET Core,Mono或.NET Framework。它们随平台一起发布,因为它们是平台的重要组成部分。所以没有必要指定一个较小的依赖集 - 一切都已经存在,你不会改变它。
NETStandard.Library
包提供了这些参考程序集。令人困惑的一点是版本号 - 软件包是版本1.6.1,但这并不意味着&#34; .NET Standard 1.6&#34;。它只是包的版本。
您定位的.NET标准版本来自您在项目中指定的目标框架。
如果您要创建一个库并希望它在.NET Standard 1.3上运行,那么您将引用NETStandard.Library
包,目前版本为1.6.1。但更重要的是,您的项目文件将定位netstandard1.3
。
NETStandard.Library
包会根据您的目标框架名字对象为您提供一组不同的引用程序集(为简洁起见,我简化了lib\netstandard1.0
,lib\netstandard1.1
和{ {3}})。因此,如果您的项目定位netstandard1.3
,您将获得1.3参考装配。如果您定位netstandard1.6
,您将获得1.6参考装配。
如果您正在创建应用程序,则无法定位.NET标准。它没有意义 - 你不能运行规范。相反,您可以定位具体平台,例如net452
或netcoreapp1.1
。 NuGet知道这些平台与netstandard
目标框架标记之间的映射,因此知道哪些lib\netstandardX.X
文件夹与您的目标平台兼容。它还知道目标平台满足NETStandard.Library
的依赖关系,因此不会引入任何其他程序集。
同样,在创建独立的.NET Core应用程序时,.NET Standard实现程序集将随您的应用程序一起复制。对NETStandard.Library
的引用不会带来任何其他新应用。
请注意dependency groups,但它目前还没有修剪,并会发布所有程序集。这将是
dotnet publish
will create a standalone application,所以再次修剪图书馆中的依赖关系在这里没有帮助。
我可以想象可能有助于删除NETStandard.Library
引用的唯一地方是,如果您的目标是不支持.NET标准的平台,那么您可以从.NET标准中找到一个包,其中所有传递依赖项都可以在目标平台上运行。我怀疑没有多少套餐可以满足这个要求。