NuGet paket bağımlılıklarını nasıl çözümler?
Geri yükleme işleminin bir parçası olarak yüklenmeyi de içeren bir paket yüklendiğinde veya yeniden yüklendiğinde NuGet, ilk paketin bağımlı olduğu tüm ek paketleri de yükler.
Bu anlık bağımlılıkların kendi bağımlılıkları da olabilir ve bu da rastgele bir derinliğe kadar devam edebilir. Bu, tüm düzeylerdeki paketler arasındaki ilişkileri açıklayan bağımlılık grafiği olarak adlandırılan bir grafik oluşturur.
Birden çok paket aynı bağımlılığına sahip olduğunda, aynı paket kimliği grafikte birden çok kez ve farklı sürüm kısıtlamalarıyla birlikte görünebilir. Ancak, projede belirli bir paketin yalnızca bir sürümü kullanılabilir, bu nedenle NuGet hangi sürümün kullanılacağını seçmelidir. Tam işlem, kullanılmakta olan paket yönetimi biçimine bağlıdır.
PackageReference ile bağımlılık çözümlemesi
PackageReference biçimini kullanarak projelere paket yüklerken, NuGet uygun dosyadaki düz bir paket grafiğine başvurular ekler ve çakışmaları önceden çözer. Bu işlem geçişli geri yükleme olarak adlandırılır. Paketlerin yeniden yüklenmesi veya geri yüklenmesi, grafikte listelenen paketleri indirme işlemidir ve bu da daha hızlı ve tahmin edilebilir derlemelere neden olur.
Projenin bir paketin en son sürümünü kullanacak şekilde değiştirilmesini önlemek için 2.8.* gibi kayan sürümlerden de yararlanabilirsiniz. Kayan sürümleri kullanırken, tekrarlanabilirliği sağlamak için kilit dosyası işlevselliğini etkinleştirmenizi öneririz.
NuGet geri yükleme işlemi bir derlemeden önce çalıştırıldığında, önce bellekte bağımlılıkları çözer, ardından sonuçta elde edilen grafiği adlı project.assets.json
bir dosyaya yazar.
Varlıklar dosyası, varsayılan olarak projenin 'obj' klasörüne sahip olan konumunda bulunur MSBuildProjectExtensionsPath
.
MSBuild daha sonra bu dosyayı okur ve olası başvuruların bulunabileceği bir klasör kümesine çevirir ve sonra bunları bellekteki proje ağacına ekler.
Dosya project.assets.json
geçicidir ve kaynak denetimine eklenmemelidir. Hem hem .tfignore
de .gitignore
içinde varsayılan olarak listelenir. Bkz. Paketler ve kaynak denetimi.
Bağımlılık çözümleme kuralları
Geçişli geri yükleme bağımlılıkları çözmek için dört ana kural uygular: en düşük geçerli sürüm, kayan sürümler, doğrudan bağımlılık-kazançları ve kuzen bağımlılıkları.
En düşük uygulanabilir sürüm
Geçerli en düşük sürüm kuralı, bir paketin bağımlılıkları tarafından tanımlandığı şekilde mümkün olan en düşük sürümünü geri yükler. Kayan olarak bildirilmediği sürece uygulama veya sınıf kitaplığındaki bağımlılıklar için de geçerlidir.
Aşağıdaki şekilde, örneğin, 1.0-beta 1.0'dan düşük olarak kabul edilir, bu nedenle NuGet 1.0 sürümünü seçer:
Sonraki şekilde, sürüm kısıtlaması = 2.1 olduğundan >, akışta sürüm 2.1 kullanılamaz, ancak NuGet bulabileceği sonraki en düşük sürümü seçer, bu durumda 2.2:
Uygulama akışta bulunmayan 1.2 gibi tam bir sürüm numarası belirttiğinde, NuGet paketi yüklemeye veya geri yüklemeye çalışırken hatayla başarısız olur:
Kayan sürümler
* karakteriyle kayan bağımlılık sürümü belirtilir. Örneğin, 6.0.*
. Bu sürüm belirtimi "en son 6.0.x sürümünü kullan" diyor; 4.*
"en son 4.x sürümünü kullan" anlamına gelir. Kayan sürümün kullanılması proje dosyasındaki değişiklikleri azaltırken bağımlılığın en son sürümünü güncel tutar.
Kayan sürümler yalnızca proje düzeyinde belirtilebilir.
Kayan sürüm kullanırken NuGet, bir paketin sürüm deseniyle eşleşen en yüksek sürümünü çözümler; örneğin 6.0.*
, bir paketin 6.0 ile başlayan en yüksek sürümünü alır:
Sürüm | Sunucuda mevcut sürümler | Çözüm | Nedeni | Notlar |
---|---|---|---|---|
* | 1.1.0 1.1.1 1.2.0 1.3.0-alfa |
1.2.0 | En yüksek kararlı sürüm. | |
1.1.* | 1.1.0 1.1.1 1.1.2-alfa 1.2.0-alfa |
1.1.1 | Belirtilen desene saygı gösteren en yüksek kararlı sürüm. | |
*-* | 1.1.0 1.1.1 1.1.2-alfa 1.3.0-beta |
1.3.0-beta | Kararlı olmayan sürümler de dahil olmak üzere en yüksek sürüm. | Visual Studio sürüm 16.6, NuGet sürüm 5.6, .NET Core SDK sürüm 3.1.300'de kullanılabilir |
1.1.*-* | 1.1.0 1.1.1 1.1.2-alfa 1.1.2-beta 1.3.0-beta |
1.1.2-beta | Desene saygılı ve kararlı olmayan sürümleri içeren en yüksek sürüm. | Visual Studio sürüm 16.6, NuGet sürüm 5.6, .NET Core SDK sürüm 3.1.300'de kullanılabilir |
Not
Kayan sürüm çözümlemesi, bir paketin listelenip listelenmediğini dikkate almaz. Koşulların Genel Paket Klasöründeki paketlerle karşılanabilmesi durumunda kayan sürüm çözümlemesi yerel olarak çözülür.
Doğrudan bağımlılık kazanır
Bir uygulamanın paket grafı aynı alt grafiğe ait bir paketin farklı sürümlerini içerdiğinde ve bu sürümlerden biri söz konusu alt grafiğe doğrudan bağımlılık olduğunda, söz konusu alt yazı için bu sürüm seçilir ve geri kalanı yoksayılır. Bu davranış, bir uygulamanın bağımlılık grafiğindeki belirli bir paket sürümünü geçersiz kılmasına olanak tanır.
Aşağıdaki örnekte, uygulama doğrudan =2.0.0 sürüm kısıtlaması >olan Paket B'ye bağlıdır. Uygulama ayrıca Paket A'ya da bağlıdır ve bu da paket B'ye bağlıdır, ancak =1.0.0 kısıtlaması vardır >. Paket B 2.0.0 bağımlılığı grafikteki uygulamaya doğrudan bağımlılık olduğundan, bu sürüm kullanılır:
Uyarı
Doğrudan bağımlılık wins kuralı, paket sürümünün düşürülerek grafikteki diğer bağımlılıkların bozulmasına neden olabilir. Bir paket eski sürüme indirildiğinde NuGet, kullanıcıyı uyarmak için bir uyarı ekler.
Bu kural ayrıca büyük bir bağımlılık grafiğiyle daha fazla verimlilik sağlar. Aynı alt grafiğe daha yakın bir bağımlılığın bir sonrakinden daha yüksek bir sürümü olduğunda, NuGet bu bağımlılığı yoksayar ve NuGet de grafın bu dalında kalan tüm bağımlılıkları yoksayar.
Örneğin, aşağıdaki diyagramda, Paket C 2.0.0 kullanıldığından, NuGet bu alt imzadaki C Paketinin önceki bir sürümüne başvuran dalları yoksayar:
Bu kural aracılığıyla NuGet, paket yazarının amacına saygı göstermeye çalışır. Aşağıdaki diyagramda, Paket A'nın yazarı açıkça Paket C 2.0.0'dan C Paketi 1.0.0'a düşürülmüştür.
Uygulama sahibi, Paket C'yi 2.0.0'dan daha yüksek bir sürüme yükseltmeyi seçebilir, bu nedenle C Paketi sürümünü daha fazla düşürmez. Bu durumda uyarı alınmaz.
Kuzen bağımlılıkları
Grafikte uygulamadan farklı paket sürümlerine farklı alt yazılarda başvurulduğunda, NuGet tüm sürüm gereksinimlerini karşılayan en düşük sürümü kullanır (geçerli en düşük sürüm ve kayan sürüm kurallarında olduğu gibi). Aşağıdaki resimde, örneğin, B Paketinin 2.0.0 sürümü diğer >=1.0.0 kısıtlamasını karşılar ve bu nedenle kullanılır:
Kuzen bağımlılıklar kuralının uygulanması için paketlerin aynı mesafede olması gerekmediğini unutmayın. Aşağıdaki diyagramda, Paket C alt imzasında Paket D 2.0.0 ve Paket A'nın alt bölümünde D 3.0.0 paketi seçilmiştir. Uygulama alt bölümünde, Paket D'ye doğrudan bağımlılık yoktur, bu nedenle en düşük geçerli sürüm kuralı uygulanır ve sürüm 3.0.0 seçilir.
Bazı durumlarda tüm sürüm gereksinimlerini karşılamak mümkün değildir. Aşağıda gösterildiği gibi, A Paketi tam olarak B 1.0.0 Paketini ve C Paketi B >=2.0.0 paketini gerektiriyorsa NuGet bağımlılıkları çözümleyemez ve bir hata verir.
Bu gibi durumlarda, En üst düzey tüketici (uygulama veya paket), Doğrudan bağımlılık kazanma kuralının geçerli olması için B Paketine kendi doğrudan bağımlılığını eklemelidir.
PackageReference ile sürüm aralıkları ve yayın öncesi sürümler
Bir paketin hem kararlı hem de yayın öncesi sürümlerinin kullanılabilir olması olağan dışı değildir.
Bir bağımlılık grafiğini çözerken NuGet, tek bir kurala dayalı olarak bir paket için yayın öncesi sürümlerin dikkate alınıp alınmayacağına karar verir: 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.
Pratikte, en düşük geçerli kural altında, bu şu anlama gelir:
Sürüm Aralığı | Kullanılabilir sürümler | Seçili sürüm |
---|---|---|
[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 | Yok, NU1103 oluşturulur. |
[1.0.0, 2.0.0-rc) | 1.2.0-beta.1, 2.0.0-beta.3 | 1.2.0-beta.1 |
packages.config ile bağımlılık çözümlemesi
ile packages.config
projenin bağımlılıkları düz bir liste olarak yazılır packages.config
. Bu paketlerin tüm bağımlılıkları da aynı listeye yazılır. Paketler yüklendiğinde NuGet dosya, app.config
, web.config
ve diğer dosyaları da değiştirebilir.csproj
.
ile packages.config
NuGet, her bir paketin yüklenmesi sırasında bağımlılık çakışmalarını çözmeyi dener. Yani, Paket A yükleniyorsa ve Paket B'ye bağlıysa ve B Paketi zaten başka bir şeyin bağımlılığı olarak listeleniyorsa packages.config
NuGet, istenen B Paketinin sürümlerini karşılaştırır ve tüm sürüm kısıtlamalarına uygun bir sürüm bulmaya çalışır. Özellikle, NuGet bağımlılıkları karşılayan alt major.minor sürümünü seçer.
Varsayılan olarak, NuGet 2.8 en düşük düzeltme eki sürümünü arar (bkz . NuGet 2.8 sürüm notları). Bu ayarı içindeki özniteliği NuGet.Config
ve komut satırındaki -DependencyVersion
anahtar aracılığıyla DependencyVersion
denetleyebilirsiniz.
Bağımlılıkları packages.config
çözümleme işlemi, daha büyük bağımlılık grafları için karmaşık hale gelir. Her yeni paket yüklemesi, grafiğin tamamının çapraz geçişini gerektirir ve sürüm çakışmaları olasılığını yükseltir. Bir çakışma oluştuğunda, yükleme durdurulur ve özellikle proje dosyasının kendisinde olası değişikliklerle proje belirsiz bir durumda bırakılır. Bu, diğer paket yönetimi biçimleri kullanılırken bir sorun değildir.
Packages.config ile sürüm aralıkları ve yayın öncesi sürümler
packages.config çözümlemesi, bir grafikte kararlı ve yayın öncesi bağımlılığın karıştırılmasını sağlamaz.
Bir bağımlılık gibi [1.0.0, 2.0.0)
bir aralıkla ifade edilirse, yayın öncesi paketlere grafikte izin verilmez.
Bağımlılık varlıklarını yönetme
PackageReference biçimini kullanırken, bağımlılıklardan hangi varlıkların en üst düzey projeye aktığını denetleyebilirsiniz. Ayrıntılar için bkz . PackageReference.
Üst düzey proje bir paket olduğunda, dosyada listelenen bağımlılıklara sahip ve exclude
özniteliklerini kullanarak include
da bu akış üzerinde denetime .nuspec
sahip olursunuz. Bkz . .nuspec Başvurusu - Bağımlılıklar.
Başvuruları dışlama
Projede aynı ada sahip derlemelere birden çok kez başvurulabileceği, tasarım zamanı ve derleme zamanı hataları oluşturan senaryolar vardır. özel sürümünü C.dll
içeren bir proje düşünün ve ayrıca içeren C.dll
C Paketine başvurur. Aynı zamanda proje, C Paketi ve C.dll
'ye de bağlı olan B Paketine de bağlıdır. Sonuç olarak, NuGet hangisinin C.dll
kullanılacağını belirleyemez, ancak B Paketi de buna bağlı olduğundan projenin C Paketi bağımlılığını kaldıramazsınız.
Bu sorunu çözmek için doğrudan istediğinize C.dll
başvurmanız (veya doğru pakete başvuran başka bir paket kullanmanız) ve ardından C Paketine tüm varlıklarını dışlayan bir bağımlılık eklemeniz gerekir. Bu, kullanımdaki paket yönetimi biçimine bağlı olarak aşağıdaki gibi yapılır:
PackageReference: bağımlılığı ekleyin
ExcludeAssets="All"
:<PackageReference Include="PackageC" Version="1.0.0" ExcludeAssets="All" />
packages.config
: PackageC'ye olan başvuruyu.csproj
dosyadan kaldırarak yalnızca istediğiniz sürümüne başvurmasınıC.dll
sağlayın.
Paket yükleme sırasında bağımlılık güncelleştirmeleri
Bir bağımlılık sürümü zaten karşılandıysa, diğer paket yüklemeleri sırasında bağımlılık güncelleştirilmez. Örneğin, B paketine bağlı olan ve sürüm numarası için 1.0'ı belirten A paketini göz önünde bulundurun. Kaynak depo B paketinin 1.0, 1.1 ve 1.2 sürümlerini içerir. A zaten B sürüm 1.0 içeren bir projeye yüklenmişse, sürüm kısıtlamasını karşıladığı için B 1.0 kullanımda kalır. Ancak, A paketinin B'nin 1.1 veya üzeri bir sürümünü istemesi durumunda B 1.2 yüklenir.
Uyumsuz paket hatalarını çözme
Paket geri yükleme işlemi sırasında "Bir veya daha fazla paket uyumlu değil..." hatasını görebilirsiniz veya bir paketin projenin hedef çerçevesiyle "uyumlu olmadığını" belirtir.
Projenizde başvuruda bulunılan paketlerden biri veya daha fazlası projenin hedef çerçevesini desteklediğini belirtmediğinde bu hata oluşur; başka bir ifadeyle paket, projeyle uyumlu bir hedef çerçeve için klasöründe uygun bir DLL lib
içermez. (Bkz. Bir liste için hedef çerçeveler .)
Örneğin, bir proje hedef alırsa ve yalnızca lib\net20
ve \lib\net45
klasörlerinde DLL'ler netstandard1.6
içeren bir paket yüklemeye çalışırsanız, paket için ve büyük olasılıkla bağımlıları için aşağıdaki gibi iletiler görürsünüz:
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'.
Uyumsuzlukları çözmek için aşağıdakilerden birini yapın:
- Projenizi, kullanmak istediğiniz paketler tarafından desteklenen bir çerçeveye yeniden hedefleyin.
- Paketlerin yazarına başvurun ve seçtiğiniz çerçeve için destek eklemek için onlarla birlikte çalışın. nuget.org'da her paket listeleme sayfasının bu amaçla bir Kişi Sahipleri bağlantısı vardır.
İpucu
Alternatif çözüm: NuGetSolver, Microsoft DevLabs tarafından geliştirilen ve bağımlılık çakışmalarını çözmeye yardımcı olmak için tasarlanmış bir Visual Studio Uzantısıdır. Bu sorunları tanımlama ve çözme sürecini otomatikleştirir. Diğer ayrıntılar için Visual Studio Market'te NuGetSolver sayfasını ziyaret edin. Deneyiminiz hakkındaki geri bildirimlerinizi duymak isteriz.