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.jsonbir 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 .tfignorede .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:

Uygun en düşük sürümü seçme

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:

Akışta kullanılabilir sonraki en düşük sürümü seçme

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:

NuGet, tam bir paket sürümü kullanılamadığında bir hata oluşturur

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:

Kayan sürüm 6.0.* istendiğinde sürüm 6.0.1'i seçme

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:

Doğrudan bağımlılık wins kuralını kullanan uygulama

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:

NuGet grafikteki bir paketi yoksaydığında, tüm dalı 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.

Bir paket yazarı açıkça eski sürüme geçtiğinde NuGet bunu kabul eder.

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.

Bir uygulama onur sürümü düşürülen paket için doğrudan bağımlılık eklediğinde, NuGet bunu kabul eder.

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:

Tüm kısıtlamaları karşılayan alt sürümü kullanarak kuzen bağımlılıklarını çözme

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.

Farklı mesafelerdeki tüm kısıtlamaları karşılayan düşük sürümü kullanarak kuzen bağımlılıklarını çözme

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.

Tam sürüm gereksinimi nedeniyle çözümlenemeyen bağımlılıklar

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.configprojenin 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.configve diğer dosyaları da değiştirebilir.csproj.

ile packages.configNuGet, 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.dlliçeren bir proje düşünün ve ayrıca içeren C.dllC 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.