Załóżmy, że mam bibliotekę klas, którą chcę kierować do netstandard1.3, ale także używam BigInteger
. Oto trywialny przykład - jedyny plik źródłowy to Adder.cs
:
using System;
using System.Numerics;
namespace Calculator
{
public class Adder
{
public static BigInteger Add(int x, int y)
=> new BigInteger(x) + new BigInteger(y);
}
}
Wracając do świata project.json
, celowałbym netstandard1.3
w tę frameworks
sekcję i mam wyraźną zależność System.Runtime.Numerics
np. Od wersji 4.0.1. Utworzony przeze mnie pakiet nuget będzie zawierał tylko tę zależność.
W nowym, odważnym świecie narzędzi dotnet opartych na csproj (używam wersji 1.0.1 narzędzi wiersza polecenia) istnieje niejawne odwołanie do pakietu metapakietuNETStandard.Library 1.6.1
podczas określania celu netstandard1.3
. Oznacza to, że mój plik projektu jest naprawdę mały, ponieważ nie wymaga wyraźnej zależności:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
</PropertyGroup>
</Project>
... ale utworzony pakiet nuget ma zależność od NETStandard.Library
, co sugeruje, że aby korzystać z mojej małej biblioteki, potrzebujesz wszystkiego .
Okazuje się, że mogę wyłączyć tę funkcję za pomocą DisableImplicitFrameworkReferences
, a następnie ręcznie dodać zależność:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard1.3</TargetFramework>
<DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Numerics" Version="4.0.1" />
</ItemGroup>
</Project>
Teraz mój pakiet NuGet mówi dokładnie, od czego zależy. Intuicyjnie wydaje się, że jest to „odchudzony” pakiet.
Jaka jest więc dokładna różnica dla konsumenta mojej biblioteki? Jeśli ktoś spróbuje go użyć w aplikacji UWP, czy druga, „przycięta” forma zależności oznacza, że wynikowa aplikacja będzie mniejsza?
Nie dokumentując DisableImplicitFrameworkReferences
jasno (o ile widziałem; przeczytałem o tym w numerze ) i ustawiając niejawną zależność jako domyślną podczas tworzenia projektu, Microsoft zachęca użytkowników do polegania tylko na metapakiecie - ale jak mogę to zrobić na pewno to nie ma wad, kiedy tworzę pakiet biblioteki klas?
źródło
Hello World!
samodzielnej aplikacji jest zmniejszony do <10 MB.Odpowiedzi:
W przeszłości
NETStandard.Library
dawaliśmy deweloperom zalecenie, aby nie odwoływać się do metapakietu ( ) z pakietów NuGet, ale zamiast tego odwoływać się do poszczególnych pakietów, takich jakSystem.Runtime
iSystem.Collections
. Powodem było to, że myśleliśmy o metapakiecie jako o skrócie dla grupy pakietów, które były rzeczywistymi atomowymi blokami budulcowymi platformy .NET. Założenie było takie: możemy w końcu stworzyć kolejną platformę .NET, która obsługuje tylko niektóre z tych atomowych bloków, ale nie wszystkie. Dlatego im mniej pakietów odwołujesz, tym bardziej będziesz przenośny. Pojawiły się również obawy dotyczące tego, jak nasze narzędzia radzą sobie z wykresami dużych pakietów.Idąc dalej, uprościmy to:
.NET Standard to atomowy blok konstrukcyjny . Innymi słowy, nowe platformy nie mogą mieć podzbioru .NET Standard - muszą to wszystko zaimplementować.
Odchodzimy od używania pakietów do opisywania naszych platform , w tym .NET Standard.
Oznacza to, że nie będziesz już musiał odwoływać się do żadnych pakietów NuGet dla platformy .NET Standard. Wyraziłeś swoją zależność od folderu lib, dokładnie tak, jak działał na wszystkich innych platformach .NET, w szczególności .NET Framework.
Jednak w tej chwili nasze narzędzia nadal będą się palić w odniesieniu do
NETStandard.Library
. Nie ma w tym nic złego, posuwanie się naprzód po prostu stanie się zbędne.Zaktualizuję często zadawane pytania dotyczące repozytorium .NET Standard, aby uwzględnić to pytanie.
Aktualizacja : to pytanie jest teraz częścią FAQ .
źródło
Zespół zalecał ustalenie, jaki jest najcieńszy zestaw opakowań. Nie robią już tego i zalecają ludziom po prostu przyniesienie NETStandard.Library (w przypadku projektu w stylu SDK zostanie to zrobione automatycznie).
Nigdy nie uzyskałem całkowicie prostej odpowiedzi na pytanie, dlaczego tak się dzieje, więc pozwól mi zrobić kilka świadomych domysłów.
Głównym powodem jest prawdopodobnie to, że pozwala im to ukryć różnice w wersjach bibliotek zależnych, które w innym przypadku musielibyście śledzić podczas zmiany platform docelowych. Jest to również znacznie bardziej przyjazny dla użytkownika system z plikami projektu opartymi na SDK, ponieważ szczerze mówiąc nie potrzebujesz żadnych odniesień, aby uzyskać przyzwoitą część platformy (tak jak kiedyś z domyślnymi referencjami w Desktop-land, zwłaszcza mscorlib ).
Wypychając meta-definicję tego, co to znaczy być
netstandard
biblioteką lubnetcoreapp
aplikacją do odpowiedniego pakietu NuGet, nie muszą oni budować żadnej specjalnej wiedzy w definicji tych rzeczy, gdy program Visual Studio (lubdotnet new
) je widzi.Analiza statyczna może zostać użyta podczas publikowania, aby ograniczyć dostarczane biblioteki DLL, co jest czymś, co robią dzisiaj, wykonując natywną kompilację dla platformy UWP (aczkolwiek z pewnymi zastrzeżeniami). Nie robią tego dzisiaj dla .NET Core, ale przypuszczam, że jest to optymalizacja, którą rozważali (a także obsługa kodu natywnego).
Nic nie stoi na przeszkodzie, abyś był bardzo selektywny, jeśli tak zdecydujesz. Wierzę, że przekonasz się, że jesteś prawie jedyną osobą, która to robi, co również mija się z celem (ponieważ zakłada się, że wszyscy wprowadzają
NETStandard.Library
lubMicrosoft.NETCore.App
).źródło
NETStandard.Library
. To nieco samospełniające, oczywiście ... jeśli mi zależećNETStandard.Library
na Noda Time, to znaczy każda inna biblioteka zbudowany na szczycie Noda Czasu nie ma powodu do wykończenia zależności itd aż korci, żeby być selektywny teraz (Noda czas zmierzając w kierunku 2.0), a potem nieco później, gdy już zostaną ustalone konwencje, rozluźnij się - zmiana z selektywnej na opartą na bibliotekach byłaby, jak zakładam, niezłomną zmianą, ale sytuacja odwrotna nie jest prawdą.Nie powinno być potrzeby wyłączania niejawnego odwołania. Wszystkie platformy, na których będzie można uruchomić bibliotekę, będą już miały zestawy, których
NETStandard.Library
wymagałaby zależność.Biblioteka .NET Standard Library to specyfikacja, zestaw zestawów referencyjnych, na podstawie których można kompilować, który zapewnia zestaw interfejsów API, które z pewnością istnieją na znanym zestawie platform i wersjach platform, takich jak .NET Core lub .NET Framework . Nie jest to implementacja tych zestawów, wystarczy kształt interfejsu API, aby umożliwić kompilatorowi pomyślne zbudowanie kodu.
Implementacja tych interfejsów API jest zapewniana przez platformę docelową, taką jak .NET Core, Mono lub .NET Framework. Są dostarczane z platformą, ponieważ są istotną częścią platformy. Nie ma więc potrzeby określania mniejszego zestawu zależności - wszystko już tam jest, nie zmienisz tego.
NETStandard.Library
Pakiet zawiera te zespoły referencyjne. Nieporozumieniem jest numer wersji - pakiet to wersja 1.6.1, ale nie oznacza to „.NET Standard 1.6”. To tylko wersja pakietu.Wersja platformy .NET Standard, na którą kierujesz reklamy, pochodzi z platformy docelowej określonej w projekcie.
Jeśli tworzysz bibliotekę i chcesz, aby działała w .NET Standard 1.3, powinieneś odwołać się do
NETStandard.Library
pakietu, obecnie w wersji 1.6.1. Ale co ważniejsze, plik projektu byłby przeznaczony dlanetstandard1.3
.NETStandard.Library
Pakiet daje innego zestawu zespołów referencyjnych w zależności od swojej docelowej ramowej pseudonimem (jestem uproszczenie dla zwięzłości, ale myślęlib\netstandard1.0
,lib\netstandard1.1
a grupy z zależnościami ). Więc jeśli Twój projekt jest przeznaczony dlanetstandard1.3
Ciebie, otrzymasz zestawy referencyjne 1.3. Jeśli celujesznetstandard1.6
, otrzymasz zestawy referencyjne 1.6.Jeśli tworzysz aplikację, nie możesz kierować na platformę .NET Standard. To nie ma sensu - nie można uruchomić na specyfikacji. Zamiast tego kierujesz reklamy na platformy betonowe, takie jak
net452
lubnetcoreapp1.1
. NuGet zna mapowanie między tymi platformami i monikerami platformynetstandard
docelowej, dzięki czemu wie, którelib\netstandardX.X
foldery są zgodne z platformą docelową. Wie również, że zależnościNETStandard.Library
są spełnione przez platformę docelową, więc nie będzie pobierać żadnych innych zestawów.Podobnie podczas tworzenia autonomicznej aplikacji .NET Core zestawy implementacji .NET Standard są kopiowane z aplikacją. Odniesienie do
NETStandard.Library
nie wprowadza żadnych innych nowych aplikacji.Jedyne miejsce, w którym mogę sobie wyobrazić, w którym może pomóc usunąć
NETStandard.Library
odwołanie, to sytuacja, w której celujesz w platformę, która nie obsługuje standardu .NET, i możesz znaleźć pakiet ze standardu .NET, w którym mogą działać wszystkie zależności przechodnie na platformie docelowej. Podejrzewam, że nie ma wielu paczek, które pasowałyby do tego rachunku.źródło
dotnet publish
to w określonym środowisku uruchomieniowym, przyniesie ono wszystkie zależności, w tym dotnet.exe (lub jego odpowiednik w systemie Linux / OS X). W tym momencie powinno to być całkowicie samodzielne wdrożenie. Sprawdź wyniki projektu testu jednostkowego: gist.github.com/bradwilson/6cc5a8fdfa18230aa6c99b851fb85c01