Jak NuGet řeší závislosti balíčků

Kdykoli se balíček nainstaluje nebo přeinstaluje, což zahrnuje instalaci v rámci procesu obnovení , NuGet také nainstaluje všechny další balíčky, na kterých závisí tento první balíček.

Tyto okamžité závislosti pak můžou mít také závislosti na sobě, což může pokračovat libovolnou hloubkou. Výsledkem je graf závislostí , který popisuje vztahy mezi balíčky na všech úrovních.

Pokud má více balíčků stejnou závislost, může se stejné ID balíčku v grafu objevit vícekrát, potenciálně s různými omezeními verze. V projektu se ale dá použít jenom jedna verze daného balíčku, takže NuGet musí zvolit, která verze se použije. Přesný proces závisí na použitém formátu správy balíčků.

Řešení závislostí pomocí PackageReference

Při instalaci balíčků do projektů pomocí formátu PackageReference přidá NuGet odkazy na plochý graf balíčků v příslušném souboru a předem vyřeší konflikty. Tento proces se označuje jako přechodné obnovení. Přeinstalace nebo obnovení balíčků je pak proces stažení balíčků uvedených v grafu, což vede k rychlejším a předvídatelnějším sestavením.

Můžete také využít plovoucí verze, například 2.8.*, abyste zabránili úpravám projektu tak, aby používal nejnovější verzi balíčku. Při použití plovoucích verzí doporučujeme povolit funkci zamknout soubor, aby se zajistila opakovatelnost.

Když se proces obnovení NuGet spustí před sestavením, vyřeší nejprve závislosti v paměti a pak zapíše výsledný graf do souboru volaný project.assets.json.

Soubor assets se nachází ve MSBuildProjectExtensionsPathvýchozím nastavení složky obj projektu. Nástroj MSBuild pak tento soubor přečte a přeloží ho do sady složek, kde lze najít potenciální odkazy, a pak je přidá do stromu projektu v paměti.

Soubor project.assets.json je dočasný a neměl by být přidán do správy zdrojového kódu. Ve výchozím nastavení je uvedena v obou .gitignore a .tfignore. Viz Balíčky a správa zdrojového kódu.

Pravidla řešení závislostí

Přechodné obnovení používá čtyři hlavní pravidla k řešení závislostí: nejnižší použitelná verze, plovoucí verze, výhry závislostí s přímým přístupem a závislosti bratrance.

Nejnižší použitelná verze

Nejnižší použitelné pravidlo verze obnoví nejnižší možnou verzi balíčku, jak je definováno jeho závislostmi. Platí také pro závislosti na aplikaci nebo knihovně tříd, pokud nejsou deklarovány jako plovoucí.

Na následujícím obrázku se například verze 1.0-beta považuje za nižší než 1.0, takže NuGet zvolí verzi 1.0:

Choosing the lowest applicable version

Na následujícím obrázku není v informačním kanálu dostupná verze 2.1, ale protože omezení verze je >= 2.1 NuGet vybere další nejnižší verzi, která může najít, v tomto případě 2.2:

Choosing the next lowest version available on the feed

Pokud aplikace určuje přesné číslo verze, například 1.2, které není dostupné v informačním kanálu, NuGet selže s chybou při pokusu o instalaci nebo obnovení balíčku:

NuGet generates an error when an exact package version is not available

Plovoucí verze

Verze s plovoucí závislostí je určena znakem *. Například 6.0.*. Tato specifikace verze říká"použití nejnovější verze 6.0.x"; 4.* znamená "použít nejnovější verzi 4.x". Použití plovoucí verze snižuje změny v souboru projektu a současně udržuje aktuální nejnovější verzi závislosti. Plovoucí verze lze zadat pouze na úrovni projektu.

Při použití plovoucí verze NuGet vyřeší nejvyšší verzi balíčku, která odpovídá vzoru verze, například 6.0.* získá nejvyšší verzi balíčku, která začíná na verzi 6.0:

Choosing version 6.0.1 when a floating version 6.0.* is requested

Verze Verze přítomné na serveru Rozlišení Důvod Notes
* 1.1.0
1.1.1
1.2.0
1.3.0-alpha
1.2.0 Nejvyšší stabilní verze.
1.1.* 1.1.0
1.1.1
1.1.2-alfa
1.2.0-alpha
1.1.1 Nejvyšší stabilní verze, která respektuje zadaný vzor.
*-* 1.1.0
1.1.1
1.1.2-alfa
1.3.0-beta
1.3.0-beta Nejvyšší verze, včetně nestabilní verze. K dispozici v sadě Visual Studio verze 16.6, NuGet verze 5.6, .NET Core SDK verze 3.1.300
1.1.*-* 1.1.0
1.1.1
1.1.2-alfa
1.1.2-beta
1.3.0-beta
1.1.2-beta Nejvyšší verze, která respektuje vzor a zahrnuje nestabilní verze. K dispozici v sadě Visual Studio verze 16.6, NuGet verze 5.6, .NET Core SDK verze 3.1.300

Poznámka:

Plovoucí rozlišení verze nebere v úvahu, jestli je uveden balíček nebo ne. Rozlišení plovoucí verze bude vyřešeno místně, pokud podmínky mohou být splněny s balíčky ve složce globálního balíčku.

Přímá závislost vyhrává

Pokud graf balíčků pro aplikaci obsahuje různé verze balíčku ve stejném podgrafu a jedna z těchto verzí je přímá závislost v tomto podgrafu, bude tato verze zvolena pro tento podgraf a zbytek bude ignorován. Toto chování umožňuje aplikaci přepsat jakoukoli konkrétní verzi balíčku v grafu závislostí.

V následujícím příkladu aplikace závisí přímo na balíčku B s omezením >verze =2.0.0. Aplikace také závisí na balíčku A, který zase závisí na balíčku B, ale s >omezením =1.0.0. Vzhledem k tomu, že závislost na balíčku B 2.0.0 je přímá závislost na aplikaci v grafu, používá se tato verze:

Application using the Direct dependency wins rule

Upozorňující

Pravidlo výhry přímé závislosti může vést k downgradu verze balíčku, čímž by mohlo dojít k narušení jiných závislostí v grafu. Když je balíček downgradován, NuGet přidá upozornění, které uživatele upozorní.

Výsledkem tohoto pravidla je také větší efektivita s velkým grafem závislostí. Pokud má užší závislost ve stejném podgrafu vyšší verzi než další, NuGet tuto závislost ignoruje a NuGet také ignoruje všechny zbývající závislosti na dané větvi grafu.

Například v následujícím diagramu, protože balíček C 2.0.0 se používá, NuGet ignoruje všechny větve v tomto podgrafu, které odkazují na starší verzi balíčku C:

When NuGet ignores a package in the graph, it ignores that entire branch

Prostřednictvím tohoto pravidla se NuGet pokusí respektovat záměr autora balíčku. V následujícím diagramu autor balíčku A explicitně downgradoval na Balíček C 1.0.0 z balíčku C 2.0.0.

When a package author explicitly downgrades, NuGet honors that.

Vlastník aplikace se může rozhodnout, že balíček C upgraduje na verzi vyšší než 2.0.0, takže verzi balíčku C nebude dále downgradovat. V tomto případě se nevyvolá žádné upozornění.

When an application honor adds a direct dependency for a downgraded package, NuGet honors that.

Závislosti bratrance

Pokud se různé verze balíčků označují v různých podgrafech v grafu z aplikace, NuGet používá nejnižší verzi, která splňuje všechny požadavky na verzi (stejně jako u nejnižší platné verze a pravidel plovoucích verzí ). Na následujícím obrázku, například verze 2.0.0 balíčku B splňuje ostatní >omezení =1.0.0, a proto se používá:

Resolving cousin dependencies using the lower version that satisfies all constraints

Mějte na paměti, že balíčky nemusí být na stejné vzdálenosti, aby pravidlo závislostí bratrance bylo možné použít. V následujícím diagramu je balíček D 2.0.0 vybrán v podgrafu Balíček C a balíček D 3.0.0 je vybrán v podgrafu balíčku A. V podgrafu aplikace neexistuje žádná přímá závislost na balíčku D, takže se použije nejnižší použitelné pravidlo verze a zvolí se verze 3.0.0.

Resolving cousin dependencies using the lower version that satisfies all constraints at different distances

V některých případech není možné splnit všechny požadavky na verzi. Jak je znázorněno níže, pokud balíček A vyžaduje přesně balíček B 1.0.0 a balíček C vyžaduje balíček B >=2.0.0, NuGet nemůže vyřešit závislosti a zobrazí chybu.

Unresolvable dependencies due to an exact version requirement

V těchto situacích by měl příjemce nejvyšší úrovně (aplikace nebo balíček) přidat vlastní přímou závislost na balíčku B, aby pravidlo wins přímé závislosti platilo.

Řešení závislostí s využitím packages.config

Se packages.configzávislostmi projektu se zapisují packages.config jako plochý seznam. Všechny závislosti těchto balíčků se také zapisují do stejného seznamu. Při instalaci balíčků může NuGet také upravit .csproj soubor, app.config, web.config, a další jednotlivé soubory.

Při packages.configinstalaci jednotlivých balíčků se NuGet pokusí vyřešit konflikty závislostí. To znamená, že pokud je balíček A nainstalovaný a závisí na balíčku B a balíček B je již uveden jako packages.config závislost něčeho jiného, NuGet porovná požadované verze balíčku B a pokusí se najít verzi, která splňuje všechna omezení verzí. NuGet konkrétně vybere nižší hlavní podverzi , která splňuje závislosti.

Ve výchozím nastavení NuGet 2.8 hledá nejnižší verzi opravy (viz poznámky k verzi NuGet 2.8). Toto nastavení můžete řídit prostřednictvím atributu DependencyVersion a NuGet.Config přepínače na příkazovém -DependencyVersion řádku.

Proces packages.config řešení závislostí je pro větší grafy závislostí složitý. Každá nová instalace balíčku vyžaduje procházení celého grafu a zvyšuje šanci na konflikty verzí. Když dojde ke konfliktu, instalace se zastaví a projekt opustí v nedeterminátu stavu, zejména při potenciálních úpravách samotného souboru projektu. Nejedná se o problém při použití jiných formátů správy balíčků.

Správa prostředků závislostí

Při použití formátu PackageReference můžete řídit, které prostředky ze závislostí proudí do projektu nejvyšší úrovně. Podrobnosti najdete v tématu PackageReference.

Pokud je projekt nejvyšší úrovně samotným balíčkem, máte také kontrolu nad tímto tokem pomocí include atributů se exclude závislostmi uvedenými v .nuspec souboru. Viz referenční informace k souboru .nuspec – závislosti.

Vyloučení odkazů

Existují scénáře, ve kterých sestavení se stejným názvem můžou být v projektu odkazována více než jednou, což vytváří chyby v době návrhu a času sestavení. Zvažte projekt, který obsahuje vlastní verzi C.dlla odkazuje na Balíček C, který obsahuje C.dlltaké . Současně projekt také závisí na balíčku B, který také závisí na balíčku C a C.dll. V důsledku toho NuGet nedokáže určit, které C.dll použít, ale nemůžete jen odebrat závislost projektu na balíčku C, protože balíček B na něm také závisí.

Pokud chcete tento problém vyřešit, musíte přímo odkazovat na C.dll požadovaný prostředek (nebo použít jiný balíček, který odkazuje na ten správný) a pak přidat závislost na balíčku C, který vylučuje všechny jeho prostředky. To se provádí následovně v závislosti na používaném formátu správy balíčků:

  • PackageReference: přidejte ExcludeAssets="All" do závislosti:

    <PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
    
  • packages.config: Odeberte odkaz na PackageC ze .csproj souboru tak, aby odkazovat pouze na požadovanou verzi C.dll .

Aktualizace závislostí během instalace balíčku

Pokud už je verze závislosti splněná, závislost se během jiných instalací balíčků neaktualizuje. Představte si například balíček A, který závisí na balíčku B a určuje číslo verze 1.0. Zdrojové úložiště obsahuje verze 1.0, 1.1 a 1.2 balíčku B. Pokud je V projektu, který již obsahuje B verze 1.0, A je nainstalován, B 1.0 zůstane používán, protože splňuje omezení verze. Pokud však balíček A požaduje verzi 1.1 nebo vyšší verze B, nainstaluje se B 1.2.

Řešení nekompatibilních chyb balíčku

Během operace obnovení balíčku se může zobrazit chyba "Jeden nebo více balíčků není kompatibilní..." nebo že balíček není kompatibilní s cílovou architekturou projektu.

K této chybě dochází, když jeden nebo více balíčků odkazovaných v projektu neznamená, že podporují cílovou architekturu projektu; to znamená, že balíček neobsahuje vhodnou knihovnu DLL ve složce lib pro cílovou architekturu, která je kompatibilní s projektem. (Viz Cílové architektury pro seznam.)

Pokud například projekt cílí netstandard1.6 a pokusíte se nainstalovat balíček, který obsahuje knihovny DLL pouze v těchto lib\net20 složkách \lib\net45 , zobrazí se zprávy podobné následujícímu balíčku a pravděpodobně jeho závislé položky:

Restoring packages for myproject.csproj...
Package ContosoUtilities 2.1.2.3 is not compatible with netstandard1.6 (.NETStandard,Version=v1.6). Package ContosoUtilities 2.1.2.3 supports:
  - net20 (.NETFramework,Version=v2.0)
  - net45 (.NETFramework,Version=v4.5)
Package ContosoCore 0.86.0 is not compatible with netstandard1.6 (.NETStandard,Version=v1.6). Package ContosoCore 0.86.0 supports:
  - 11 (11,Version=v0.0)
  - net20 (.NETFramework,Version=v2.0)
  - sl3 (Silverlight,Version=v3.0)
  - sl4 (Silverlight,Version=v4.0)
One or more packages are incompatible with .NETStandard,Version=v1.6.
Package restore failed. Rolling back package changes for 'MyProject'.

Pokud chcete vyřešit nekompatibilitu, udělejte jednu z těchto věcí:

  • Nastavte cílení projektu na architekturu podporovanou balíčky, které chcete použít.
  • Obraťte se na autora balíčků a spolupracujte s nimi a přidejte podporu pro vámi zvolenou architekturu. Každá stránka s výpisem balíčku na nuget.org má pro tento účel odkaz Kontaktovat vlastníky.

Tip

Alternativní řešení: NuGetSolver je rozšíření sady Visual Studio vyvinuté Microsoft DevLabs, které je navržené tak, aby pomohlo vyřešit konflikty závislostí. Automatizuje proces identifikace a řešení těchto problémů. Další podrobnosti najdete na stránce NuGetSolver na webu Visual Studio Marketplace a rádi si poslechneme váš názor na vaše prostředí.