Sdílet prostřednictvím


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 mohou mít také své vlastní závislosti, což může pokračovat do libovolné hloubky. To vytvoří 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 tranzitivní 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 uzamknout soubor, aby se zajistila opakovatelnost.

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

Soubor assets se nachází v MSBuildProjectExtensionsPath, který ve výchozím nastavení odkazuje na složku 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 uvedený v .gitignore i v .tfignore. Viz Balíčky aspráva zdrojového kódu.

Pravidla řešení závislostí

Přechodné obnovení používá čtyři hlavní pravidla pro řešení závislostí: nejnižší použitelné verze, plovoucí verze, vítězství přímé závislostia příbuzné závislosti.

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:

Výběr nejnižší použitelné verze

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

Výběr nejbližší nižší verze dostupné v informačním kanálu

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 vygeneruje chybu, pokud není k dispozici přesná verze balíčku

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žití nejnovější verze 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:

výběr verze 6.0.1 při vyžádání plovoucí verze 6.0.*

Verze Verze přítomné na serveru Usnesení Důvod Poznámky
* 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. Dostupné v sadě Visual Studio ve verzi 16.6, NuGet ve verzi 5.6, .NET Core SDK ve verzi 3.1.300
1.2.0-rc.* 1.1.0
1.2.0-rc.1
1.2.0-rc.2
1.2.0
1.2.0 Navzdory tomu, že jde o rozsah verzí s předběžnou částí, jsou stabilní verze povoleny, pokud se shodují se stabilní částí. Vzhledem k tomu, že 1.2.0 > 1.2.0-rc.2, je zvolen.

Poznámka

Plovoucí rozlišení verze nebere v úvahu, jestli je uveden balíček nebo ne. Řešení pohyblivých verzí bude provedeno na místní úrovni, pokud podmínky mohou být splněny pomocí balíčků 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:

aplikace využívající pravidlo wins přímé závislosti

Varování

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í , aby uživatele upozornil.

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:

Když NuGet ignoruje balíček v grafu, ignoruje celou větev

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.

Když autor balíčku explicitně downgraduje, NuGet to respektuje.

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í.

Když aplikace čest přidá přímou závislost pro downgradovaný balíček, NuGet to respektuje.

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žší použitelné verze a plovoucí verze pravidla). Na následujícím obrázku, například verze 2.0.0 balíčku B splňuje ostatní >=1.0.0 omezení, a proto se používá:

Řešení závislostí bratrance pomocí nižší verze, která splňuje všechna omezení

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 přímá závislost na balíčku D, takže se použije pravidlo nejnižší použitelné verze a zvolí se verze 3.0.0.

řešení závislostí bratrance pomocí nižší verze, která splňuje všechna omezení v různých vzdálenostech

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.

nevyřešitelné závislosti kvůli přesnému požadavku na verzi

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 přímá závislost vyhrála pravidlo.

Rozsahy verzí a předběžné verze pomocí PackageReference

Není neobvyklé, že balíček bude mít k dispozici stabilní i předběžné verze. Při řešení grafu závislostí se NuGet rozhodne, jestli se má zvážit předběžné verze balíčku na základě jednoho pravidla: If the project or any packages within the graph request a prerelease version of a package, then include both prerelease or stable versions, otherwise consider stable versions only.

V praxi platí, že v rámci nejnižšího platného pravidla to znamená:

Rozsah verzí Dostupné verze Vybraná verze
[1.0.0, 2.0.0) 1.2.0-beta.1, 1.2.0, 1.2.0
[1.0.0, 2.0.0-0) 1.2.0-beta.1, 1.2.0, 1.2.0-beta.1
[1.0.0, 2.0.0) 1.2.0-beta.1, 2.0.0-beta.3 Žádné, NU1103 je vyvolána.
[1.0.0, 2.0.0-rc) 1.2.0-beta.1, 2.0.0-beta.3 1.2.0-beta.1

Řešení závislostí s packages.config

S packages.configse závislosti projektu zapisují do 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 soubor .csproj, app.config, web.configa další jednotlivé soubory.

Při packages.configse NuGet pokusí vyřešit konflikty závislostí během instalace jednotlivých balíčků. To znamená, že pokud je balíček A nainstalovaný a závisí na balíčku B a balíček B je již uveden v packages.config jako 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í verze. NuGet konkrétně vybere nižší verzi major.minor, 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 v NuGet.Config a přepínačem -DependencyVersion na příkazovém řádku.

Proces packages.config pro řešení závislostí se pro větší grafy závislostí zkomplikuje. 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 zůstane v neurčitém stavu, zvláště 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ů.

Rozsahy verzí a předběžné verze s packages.config

packages.config rozlišení neumožňuje míchání stabilních a předběžných závislostí v grafu. Pokud je závislost vyjádřena s rozsahem, jako je [1.0.0, 2.0.0), nejsou v grafu povolené předběžné balíčky.

Správa majetků 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 části PackageReference.

Pokud je projekt nejvyšší úrovně samotným balíčkem, máte také kontrolu nad tímto tokem pomocí include a exclude atributů se závislostmi uvedenými v souboru .nuspec. Viz referenci .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 také C.dll. 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 jenom 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 označit C.dll, který chcete (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 zdroje. To se provádí následovně v závislosti na používaném formátu správy balíčků:

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

    <PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
    
  • packages.config: Odeberte odkaz na PackageC ze souboru .csproj, tak, aby odkazoval 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, nainstalováno A, pak B 1.0 zůstává v použití, 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. (Seznam najdete v cílových rámců.)

Pokud například projekt cílí na netstandard1.6 a vy se pokusíte nainstalovat balíček, který obsahuje knihovny DLL pouze ve složkách lib\net20 a \lib\net45, zobrazí se zprávy podobné těmto pro balíček a pravděpodobně i pro jeho závislosti:

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. Pro tento účel má každá stránka s výpisem balíčku na nuget.org odkaz Kontaktovat vlastníky.

Spropitné

alternativní řešení: NuGetSolver je rozšíření sady Visual Studio vyvinuté Microsoft DevLabs, které pomáhá ř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í.