Výběr sestavení odkazovaných podle projektů

Sestavení se během sestavení používají dvěma různými způsoby. První je kompilace, která umožňuje kódu příjemce balíčku zkompilovat proti rozhraním API v sestavení a intellisense poskytnout návrhy. Druhým modulem je modul runtime, kde se sestavení zkopíruje do bin adresáře a používá se během provádění programu. Někteří autoři balíčků chtějí v době kompilace pouze svá vlastní sestavení (nebo podmnožinu jejich sestavení), ale potřebují poskytnout všechny jejich závislosti za běhu. Tento dokument popisuje způsoby, jak dosáhnout tohoto výsledku.

Naším doporučením je mít jeden balíček na sestavení a závislosti balíčků na jiná sestavení. Když NuGet obnoví projekt, provede výběr prostředků a podporuje zahrnutí, vyloučení a vytváření soukromých tříd prostředků. Pokud chcete zabránit tomu, aby se závislosti balíčku staly prostředky času kompilace pro každého, kdo používá váš balíček, můžete prostředky nastavit compile jako soukromé. Ve vygenerovaném balíčku to způsobí compile vyloučení z závislosti. Všimněte si, že výchozí privátní prostředky, pokud není zadán contentfiles;build;analyzersžádný . Proto byste měli použít PrivateAssets="compile;contentfiles;build;analyzers" ve svém PackageReference nebo ProjectReference.

<ItemGroup>
  <ProjectReference Include="..\OtherProject\OtherProject.csproj" PrivateAssets="compile;contentfiles;build;analyzers" />
  <PackageReference Include="SomePackage" Version="1.2.3" PrivateAssets="compile;contentfiles;build;analyzers" />
</ItemGroup>

Pokud vytváříte balíček z vlastního nuspec souboru a nepustíte ho automaticky vygenerovat NuGet, měli byste nuspec použít exclude atribut XML .

<dependencies>
  <group targetFramework=".NETFramework4.8">
    <dependency id="OtherProject" version="3.2.1" exclude="Compile,Build,Analyzers" />
    <dependency id="SomePackage" version="1.2.3" exclude="Compile,Build,Analyzers" />
  </group>
</dependencies>

Toto je doporučené řešení ze tří důvodů.

Za prvé, užitečné sestavení často odkazují na nová sestavení/balíčky. Zatímco sestavení nástroje může být určeno pouze pro použití jednoho balíčku dnes, takže je lákavé dodávat obě sestavení v jednom balíčku, pokud druhý balíček chce použít "privátní" sestavení nástroje v budoucnu, musí být buď přesunuto do nového balíčku a starý balíček musí být aktualizován, aby ho deklaroval jako závislost, nebo balíček nástroje musí být dodáván v existujícím i novém balíčku. Pokud se sestavení dodává ve dvou různých balíčcích a projekt odkazuje na oba balíčky, pokud existují různé verze sestavení nástroje ve dvou balíčcích, NuGet nebude moct pomoct se správou verzí.

Za druhé může docházet k tomu, že vývojáři, kteří váš balíček používají, chtějí také používat rozhraní API z vašich závislostí. Představte si například balíček Microsoft.ServiceHub.Client verze 3.0.3078. Pokud balíček stáhnete a zkontrolujete nuspec soubor, uvidíte, že obsahuje dva balíčky začínající Microsoft.VisualStudio. jako závislosti, což znamená, že je potřebuje za běhu, ale zároveň vylučuje jejich kompilační prostředky. To znamená, že projekty používající Microsoft.ServiceHub.Client nebudou mít v IntelliSense k dispozici rozhraní API sady Visual Studio nebo pokud projekt explicitně nenainstaluje. A to je výhoda, kterou má závislost balíčku s vyloučeným assetem. Projekty používající váš balíček, pokud chtějí používat i vaše závislosti, můžou do balíčku přidat odkaz, aby byla rozhraní API k dispozici pro sebe.

A konečně, někteří autoři balíčků byli v minulosti zmateni o výběru sestavení NuGet pro balíčky podporující více než jednu cílovou architekturu, pokud jejich balíček obsahuje také více sestavení. Pokud vaše hlavní sestavení podporuje různé cílové architektury pro vaše sestavení nástroje, nemusí být zřejmé, do kterých lib/ adresářů mají být všechna sestavení vložena. Když jednotlivé balíčky rozdělíte podle názvu sestavení, je intuitivnější, do kterých lib/ složek by se každé sestavení mělo přejít. Všimněte si, že to neznamená mít Package1.net48 a Package1.net6.0 balíčky. To znamená mít lib/net48/Package1.dll a lib/net6.0/Package6.0 v Package1, a lib/netstandard2.0/Package2.dlllib/net5.0/Package2.dll v Package2. Když NuGet obnoví projekt, NuGet nezávisle provede výběr prostředku pro oba balíčky.

Všimněte si také, že prostředky zahrnutí/vyloučení závislostí používají pouze projekty využívající PackageReference. Každý projekt, který nainstaluje balíček pomocí, packages.config nainstaluje vaše závislosti a bude mít k dispozici i jeho rozhraní API. packages.config podporuje pouze starší šablony projektů .NET Framework sady Visual Studio. Projekty stylu sady SDK, i ty, které cílí na rozhraní .NET Framework, nepodporují packages.config, a proto podporují závislost zahrnutí nebo vyloučení prostředků.

PackageReference a packages.config mají k dispozici různé funkce. Bez ohledu na to, jestli chcete podporovat uživatele balíčků, kteří používají PackageReference, packages.confignebo obojí, změní způsob vytváření balíčku.

Cíl balíčku MSBuild NuGet nepodporuje automatické zahrnutí odkazů na projekt v balíčku. Zobrazí pouze odkazované projekty jako závislosti balíčků. Na GitHubu došlo k problému, kdy členové komunity sdíleli způsoby, jak tohoto výsledku dosáhli, což obvykle zahrnuje použití PackagePath metadat položek NÁSTROJE MSBuild k umístění souborů kdekoli v balíčku, jak je popsáno v dokumentaci k zahrnutí obsahu do balíčku, a použití kSuppressDependenciesWhenPackingtomu, aby se odkazy na projekt staly závislostmi balíčků. Existují také komunitní vyvinuté nástroje, které lze použít jako alternativu k oficiálnímu balíčku NuGet, který tuto funkci podporuje.

PackageReference Podporu

Když uživatel balíčku použije PackageReference, NuGet vybere prostředky kompilace a modulu runtime nezávisle, jak je popsáno výše.

Kompilujte prostředky raději ref/<tfm>/*.dll (například ref/net6.0/*.dll), ale pokud neexistuje, vrátí se zpět lib/<tfm>/*.dll (například lib/net6.0/*.dll).

Runtime assety preferují runtimes/<rid>/lib/<tfm>/*.dll (například (runtimes/win11-x64/lib/net6.0/*.dll)), ale pokud neexistuje, pak se vrátí zpět na lib/<tfm>/*.dll.

Vzhledem k tomu, že sestavení nejsou ref\<tfm>\ používána za běhu, mohou se jednat o sestavení pouze metadata , aby se snížila velikost balíčku.

packages.config Podporu

Projekty, které používají packages.config ke správě balíčků NuGet, obvykle přidávají odkazy na všechna sestavení v lib\<tfm>\ adresáři. Adresář ref\ byl přidán do podpory PackageReference , a proto není při použití packages.configpovažován za . Chcete-li explicitně nastavit, která sestavení jsou odkazována pro projekty používající packages.config, balíček musí použít <references> prvek v souboru nuspec. Příklad:

<references>
    <group targetFramework="net45">
        <reference file="MyLibrary.dll" />
    </group>
</references>

Cíle balíčku MSBuild nepodporují <references> element. Podívejte se na dokumentaci k balení pomocí souboru .nuspec při použití balíčku MSBuild.

Poznámka:

packages.config Project používá proces s názvem ResolveAssemblyReference ke kopírování sestavení do výstupního bin\<configuration>\ adresáře. Sestavení projektu se zkopíruje a systém sestavení pak pro všechna sestavení rekurzivně zopakuje manifest sestavení pro odkazovaná sestavení, pak tato sestavení zkopíruje a rekurzivně opakuje. To znamená, že pokud některá sestavení načtená pouze reflexí (Assembly.LoadMEF nebo jinou architekturou injektáže závislostí), nemusí být zkopírována do výstupního bin\<configuration>\ adresáře projektu, přestože je v bin\<tfm>\. To také znamená, že to funguje jenom pro sestavení .NET, ne pro nativní kód volaný pomocí volání P/Invoke.

Podpora obou PackageReference a packages.config

Důležité

Pokud balíček obsahuje element nuspec <references> a neobsahuje sestavení v ref\<tfm>\, NuGet inzeruje sestavení uvedená v prvku nuspec <references> jako prostředky kompilace i modulu runtime. To znamená, že dojde k výjimkám za běhu, když odkazovaná sestavení musí načíst jakékoli jiné sestavení v lib\<tfm>\ adresáři. Proto je důležité použít jak nuspec <references> pro packages.config podporu, tak duplikování sestavení ve ref/ složce pro PackageReference podporu. Složku runtimes/ balíčku není nutné použít, byla přidána do výše uvedené části, aby byla dokončena.

Příklad

Balíček bude obsahovat tři sestavení a MyLib.dllMyHelpers.dllMyUtilities.dll, které cílí na rozhraní .NET Framework 4.7.2. MyUtilities.dll obsahuje třídy, které mají být používány pouze ostatními dvěma sestaveními, takže nechci tyto třídy zpřístupnit v IntelliSense ani v době kompilace pro projekty používající můj balíček. Soubor nuspec musí obsahovat následující elementy XML:

<references>
    <group targetFramework="net472">
        <reference file="MyLib.dll" />
        <reference file="MyHelpers.dll" />
    </group>
</references>

Potřebuji zajistit, aby obsah balíčku:

lib\net472\MyLib.dll
lib\net472\MyHelpers.dll
lib\net472\MyUtilities.dll
ref\net472\MyLib.dll
ref\net472\MyHelpers.dll