2017-11-18 135 views
6

Zaczynałem się z a .NET Standard project i NuGet. Mam działający projekt i mam uploaded it to NuGet.org. Mój projekt jest ukierunkowany na .NET Standard 1.3, który jest dostępny w wersjach .NET Framework 4.6 i .NET Core 1.0.Dlaczego mój pakiet .NET Standard NuGet wyzwala tak wiele zależności?

Ale kiedy próbowałem dodać mój projekt (przez NuGet) do nowego projektu .NET Framework 4.6, zależności zostały rozwiązane na pakiety ! Wszystkie są bibliotekami systemowymi i wydają się być zależne od Microsoft.NETCore.Platforms lub NETStandard.Library 1.6.1. (Gist of full PM output.)

Mój projekt tylko importuje (using) garść bibliotek, z których żadna nie została dodana ręcznie; tj. wszystkie są bibliotekami, które "pochodzą z" .NET Standard. Biblioteki te są następujące:

  1. systemu
  2. System.Text
  3. System.Reflection
  4. System.Linq
  5. System.Collections.Generic;

Chodzi o to, że zdecydowałem się uczynić mój projekt docelowy .NET Standard, ponieważ chciałem, aby działał bezproblemowo w aplikacjach .NET Framework i .NET Core. Sądziłem, że celem standardu jest ustalenie minimalnego poziomu kompatybilności. Sądzę, że założyłem (być może błędnie), że biblioteki takie jak System.Console będą automatycznie dostępne w Core lub Framework.

Nie zauważyłem czegoś takiego, kiedy testowałem swój projekt Standard jako zależność w projekcie ramowym i rdzeniowym w ramach tego samego rozwiązania, więc jestem podejrzliwy, że może to być sprawa NuGet.

Co się tutaj naprawdę dzieje? A jak mogę udostępnić moją bibliotekę .NET Standard na NuGet bez ogromnej listy zależności?

Czy to jest problem ze sposobem, w jaki określiłem mój pakiet NuGet? Czy też zasadniczo coś źle zrozumiałem?

+0

Czy zauważyłeś, że cokolwiek jest faktycznie dodawane do folderu wyjściowego, czy jest to po prostu przerażająca lista zależności podczas instalowania pakietu? Moje doświadczenie jest takie, że to drugie, które nadal nie jest wspaniałe, ale nie tak niepokojące. –

+0

@JonSkeet W folderze Moje paczki znajduje się długa lista folderów, kiedy naprawdę się tego spodziewałem. Dodatkowo, ekran "zarządzaj pakietami NuGet" pokazuje wszystkie pakiety (niektóre z nich mają oczekujące aktualizacje). –

+2

Dobrze - ale co znajduje się w katalogu bin? (FWIW, całkowicie zgadzam się, że jest to bardzo niefortunna sytuacja.Nie wiem, czy został ulepszony w późniejszych wersjach. Ale właśnie dlatego dla niektórych pakietów, które produkuję, tworzę cel net45, a także wersję netstandard1.x ...) –

Odpowiedz

9

Nie zrobiliście nic złego, tak się powinno stać. Jeśli nie chcesz nic więcej, jak tylko dodałeś własną bibliotekę DLL do nowego projektu .NET Framework, musisz skierować .NET Standard 2.0 do swojej biblioteki. Poczekaj na wersję .NET Framework, która natywnie obsługuje zarówno wersję API, jak i wersję zestawu - która idzie w parze do wersji 4.7.2 (podczas gdy platforma .NET Framework 4.7.1 obsługuje wszystkie interfejsy API, pojawiły się błędy dotyczące sposobu wersjonowania niektórych zespołów, a więc oprzyrządowanie (VS 2017 15.5+) doda dodatkowe zespoły, aby to naprawić).

To, co widzisz, jest efektem ubocznym budowania .NET Standard i implementacji obsługi obsługiwanych frameworków. Różni się także w zależności od wybranej wersji .NET Standard i narzędzi używanych do odwoływania się do pakietu bibliotek.

W standardzie .NET Standard < 2.0 odwołujesz się do meta-pakietu NETStandard.Library, który z kolei odwołuje się do dodatkowych pakietów (System.*). Pakiety te zawierają zespoły referencyjne, które składają się na "Kontrakt standardowy .NET" - zestaw interfejsów API oraz nazwy i wersje zespołów.

Gdy pakiet NuGet, który utworzysz dla .NET Standard 1.0-1.6, jest następnie wywoływany przez aplikację, te indywidualne pakiety nie zawierają zestawów odwołań, lecz raczej zespoły wdrożeniowe dla szkieletu, na który aplikacja jest przeznaczona.

Dla .NET Core odpowiadają one zespołom, które są już częścią środowiska wykonawczego, więc pliki DLL nie znajdą się obok utworzonej aplikacji. Zmieniło się to jednak po wydaniu nowego zestawu pakietów dla .NET Core 1.1 (NETStandard.Library wersja 1.6.1). W efekcie powstały aplikacje stworzone dla .NET Core 1.0, kończące coraz nowsze zespoły wdrożeniowe, które miały zostać włączone do .NET Core 1.1 (na szczęscie, wersja 1.1 była wersją "długoterminowego wsparcia", ponieważ wywołała dyskusję o tym, które zgromadzenia są częścią obietnicy LTS).

W bibliotekach .NET Framework te biblioteki (z pewnymi wyjątkami, takimi jak System.Net.Http) nie robią zbyt wiele - po prostu przesyłają dalej do złożeń systemu. Na przykład "umowa" definiuje, że System.Object jest zdefiniowany w zespole System.Runtime.dll. Tak więc plik System.Runtime.dll, w którym kończy się aplikacja .NET Framework, zawiera System.Runtime.dll, który zawiera typ przekazany dalej do .NET Framework o nazwie mscorlib.dll. .NET Core zawiera już inny System.Runtime.dll, który robi coś innego dla tej platformy. Mechanizm ten pozwala na działanie pojedynczego pliku DLL na obu platformach, ponieważ tego typu przekazywanie i dodatkowe implementacje zapewniają taką samą "umowę" (typy + złoŜenia + wersje montaŜowe) działające na obu implementacjach.

.NET Standard 2.0 ma na celu zmniejszenie liczby pakietów i bibliotek DLL, które są niezbędne, a także usunięcie wymagających aktualizacji do NETStandard.Library po wydaniu nowej wersji .NET Core.

W przypadku .NET Standard 2.0 i .NET Core 2.0, pakiet NETStandard.Library dostarcza tylko zestawy referencyjne do kompilowania kodu do projektu, ale wynikowy pakiet NuGet nie jest już zależny od tego pakietu. Więc kiedy utworzysz bibliotekę targetującą .NET Standard 2.0 i ją opublikujesz, nie będzie ona miała zależności NuGet (chyba że dodasz dodatkowe).

Logika tego, co "biblioteki wsparcia" wprowadzają podczas używania biblioteki .NET Standard została przeniesiona do narzędzia używanego podczas kompilacji. Kiedy więc biblioteka zawierająca odniesienie do netstandard.dll zostanie dodana do projektu .NET Framework, narzędzie będzie następnie dodawać niezbędne biblioteki pomocnicze w zależności od używanej wersji .NET Framework. Zrobiono to dla .NET Standard 2.0, a także .NET Standard 1.5+ od .NET Framework 4.6.1 był wstecznie kompatybilny z .NET Standard 2.0 (był wcześniej 1.4) poprzez tego rodzaju pliki DLL. To samo narzędzie zapewnia również, że nawet jeśli pakiety NuGet zostaną w jakiś sposób wprowadzone do takiego projektu aplikacji, wszelkie biblioteki implementacji .NET Standard wprowadzone przez NuGet zostaną usunięte z kompilacji. Jeśli więc odwołasz się do pakietu .NET Standard 1.0 NuGet, który został zbudowany po wydaniu .NET Core 1.0, wszystkie jego zależności NuGet zostaną usunięte i otrzymasz zamiast tego biblioteki wsparcia z opcją budowania.

Pomysł polegał na tym, że .NET Framework 4.7.1 zawierałby wszystkie niezbędne zestawy "skrzynkę odbiorczą", dzięki czemu netstandard.dll, System.Runtime.dll itd. Są częścią .NET Framework, a każdy plik DLL .NET Standard 1.0-2.0 byłby "po prostu" praca ", problem polegał na tym, że te pliki dll" skrzynki odbiorczej "miały zbyt niski numer wersji dla niektórych zespołów, więc biblioteki nie mogły się załadować - zostało to naprawione poprzez zmianę narzędzi w celu dołączenia plików DLL o wyższych numerach wersji jako bibliotek pomocniczych, które w przejdź do zsynchronizowanych zestawów .NET Framework. Zostanie to naprawione w programie .NET Framework 4.7.2.

+0

Dzięki Martin. Zajęło mi trochę czasu, aby w pełni przetrawić tę bardzo wyczerpującą odpowiedź. Przypuszczam, że .NET Standard jest wciąż w powijakach i to jest jeden z bólów ząbkowania. Będę siedzieć napięty i czekać na wersję 4.7.2 Framework. –

+0

Moja uwaga została zwrócona na obejście problemu: http://blog.tdwright.co.uk/2017/11/21/update-getting-net-standard-apps-playing-nicely-on-nuget/ –

+1

Tak, NuGet's logika "get-nearest-framework" preferuje tę samą strukturę docelową w niższych wersjach przed uwzględnieniem innych (więc projekt 'net471' będzie nawet wybierał' net35' przez 'netstandard2.0') –