Odwoływanie się do zestawów
Zestawy referencyjne to specjalny typ zestawu, który zawiera tylko minimalną ilość metadanych wymaganych do reprezentowania publicznej powierzchni interfejsu API biblioteki. Obejmują deklaracje wszystkich elementów członkowskich, które są istotne podczas odwoływania się do zestawu w narzędziach kompilacji, ale wykluczają wszystkie implementacje składowych i deklaracje prywatnych elementów członkowskich, które nie mają zauważalnego wpływu na kontrakt interfejsu API. Z kolei regularne zestawy są nazywane zestawami implementacji.
Nie można załadować zestawów odwołań do wykonania, ale mogą być przekazywane jako dane wejściowe kompilatora w taki sam sposób, jak zestawy implementacji. Zestawy referencyjne są zwykle dystrybuowane za pomocą zestawu Software Development Kit (SDK) określonej platformy lub biblioteki.
Użycie zestawu referencyjnego umożliwia deweloperom tworzenie programów przeznaczonych dla określonej wersji biblioteki bez posiadania pełnego zestawu implementacji dla tej wersji. Załóżmy, że masz tylko najnowszą wersję biblioteki na komputerze, ale chcesz utworzyć program przeznaczony dla starszej wersji tej biblioteki. Jeśli skompilujesz bezpośrednio zestaw implementacji, możesz przypadkowo użyć elementów członkowskich interfejsu API, które nie są dostępne we wcześniejszej wersji. Ten błąd można znaleźć tylko podczas testowania programu na maszynie docelowej. Jeśli skompilujesz zestaw referencyjny dla starszej wersji, natychmiast zostanie wyświetlony błąd czasu kompilacji.
Zestaw referencyjny może również reprezentować kontrakt, czyli zestaw interfejsów API, które nie odpowiadają konkretnemu zestawowi implementacji. Takie zestawy referencyjne, nazywane zestawem kontraktu, mogą służyć do określania celu wielu platform obsługujących ten sam zestaw interfejsów API. Na przykład platforma .NET Standard udostępnia zestaw kontraktów, netstandard.dll, który reprezentuje zestaw typowych interfejsów API udostępnianych między różnymi platformami .NET. Implementacje tych interfejsów API znajdują się w różnych zestawach na różnych platformach, takich jak mscorlib.dll w programie .NET Framework lub System.Private.CoreLib.dll na platformie .NET Core. Biblioteka przeznaczona dla platformy .NET Standard może działać na wszystkich platformach obsługujących platformę .NET Standard.
Korzystanie z zestawów odwołań
Aby używać niektórych interfejsów API z projektu, należy dodać odwołania do ich zestawów. Można dodawać odwołania do zestawów implementacji lub odwołać się do zestawów. Zaleca się używanie zestawów odwołań za każdym razem, gdy są dostępne. Zapewnia to, że używasz tylko obsługiwanych elementów członkowskich interfejsu API w wersji docelowej, które mają być używane przez projektantów interfejsu API. Użycie zestawu referencyjnego gwarantuje, że nie masz zależności od szczegółów implementacji.
Zestawy referencyjne dla bibliotek programu .NET Framework są dystrybuowane za pomocą pakietów docelowych. Można je uzyskać, pobierając autonomiczny instalator lub wybierając składnik w instalatorze programu Visual Studio. Aby uzyskać więcej informacji, zobacz Instalowanie programu .NET Framework dla deweloperów. W przypadku platform .NET Core i .NET Standard zestawy referencyjne są automatycznie pobierane w razie potrzeby (za pośrednictwem narzędzia NuGet) i przywoływane. W przypadku platformy .NET Core 3.0 i nowszych zestawy referencyjne dla platformy podstawowej znajdują się w pakiecie Microsoft.NETCore.App.Ref ( pakiet Microsoft.NETCore.App jest używany zamiast wersji wcześniejszych niż 3.0).
Po dodaniu odwołań do zestawów .NET Framework w programie Visual Studio przy użyciu okna dialogowego Dodawanie odwołania wybierasz zestaw z listy, a program Visual Studio automatycznie odnajduje zestawy referencyjne odpowiadające wersji platformy docelowej wybranej w projekcie. To samo dotyczy dodawania odwołań bezpośrednio do projektu MSBuild przy użyciu elementu projektu Odwołanie : wystarczy określić nazwę zestawu, a nie pełną ścieżkę pliku. W przypadku dodawania odwołań do tych zestawów w wierszu polecenia przy użyciu -reference
opcji kompilatora (w języku C# i Visual Basic) lub przy użyciu Compilation.AddReferences metody w interfejsie API Roslyn należy ręcznie określić pliki zestawów odwołań dla odpowiedniej wersji platformy docelowej. Pliki zestawu referencyjnego programu .NET Framework znajdują się w folderze %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\. KATALOG NETFramework . W przypadku platformy .NET Core można wymusić operację publikowania w celu skopiowania zestawów odwołań dla platformy docelowej do podkatalogu publish/refs katalogu wyjściowego, ustawiając PreserveCompilationContext
właściwość projektu na true
. Następnie możesz przekazać te pliki zestawu referencyjnego do kompilatora. Użycie z DependencyContext
pakietu Microsoft.Extensions.DependencyModel może pomóc w zlokalizowaniu ich ścieżek.
Ponieważ nie zawierają implementacji, nie można załadować zestawów odwołań do wykonania. Próba wykonania tej czynności powoduje wyświetlenie ciągu System.BadImageFormatException. Jeśli chcesz sprawdzić zawartość zestawu referencyjnego, możesz załadować go do kontekstu tylko odbicia w programie .NET Framework (przy użyciu Assembly.ReflectionOnlyLoad metody) lub w MetadataLoadContext programach .NET Framework i .NET Framework.
Generowanie zestawów odwołań
Generowanie zestawów odwołań dla bibliotek może być przydatne, gdy użytkownicy biblioteki muszą skompilować swoje programy w wielu różnych wersjach biblioteki. Dystrybucja zestawów implementacji dla wszystkich tych wersji może być niepraktyczna ze względu na ich duży rozmiar. Zestawy referencyjne są mniejsze i dystrybuują je jako część zestawu SDK biblioteki, co zmniejsza rozmiar pobierania i oszczędza miejsce na dysku.
Środowiska IDE i narzędzia kompilacji mogą również korzystać z zestawów referencyjnych, aby skrócić czas kompilacji w przypadku dużych rozwiązań składających się z wielu bibliotek klas. Zazwyczaj w scenariuszach kompilacji przyrostowej projekt jest ponownie kompilowany po zmianie dowolnego z jego plików wejściowych, w tym zestawów, od których zależy. Zestaw implementacji zmienia się za każdym razem, gdy programista zmienia implementację dowolnego elementu członkowskiego. Zestaw referencyjny zmienia się tylko wtedy, gdy ma to wpływ na jego publiczny interfejs API. Dlatego użycie zestawu referencyjnego jako pliku wejściowego zamiast zestawu implementacji umożliwia pominięcie kompilacji projektu zależnego w niektórych przypadkach.
Zestawy referencyjne można wygenerować:
- W projekcie MSBuild przy użyciu
ProduceReferenceAssembly
właściwości projektu. - Podczas kompilowania programu z poziomu wiersza polecenia należy określić
-refonly
opcje kompilatora (C# / Visual Basic) lub-refout
(C# / Visual Basic). - W przypadku korzystania z interfejsu API Roslyn przez ustawienie EmitOptions.EmitMetadataOnly na
true
i EmitOptions.IncludePrivateMembers wfalse
obiekcie przekazanym Compilation.Emit do metody .
Jeśli chcesz dystrybuować zestawy odwołań za pomocą pakietów NuGet, musisz uwzględnić je w podkatalogu ref\ w katalogu pakietów zamiast w podkatalogu lib\ używanego do implementacji zestawów.
Struktura zestawów odwołań
Zestawy referencyjne to rozszerzenie powiązanej koncepcji, zestawów tylko metadanych. Zestawy tylko do metadanych mają treść metody zastąpioną pojedynczą throw null
treścią, ale zawierają wszystkie elementy członkowskie z wyjątkiem typów anonimowych. Przyczyną używania throw null
ciał (w przeciwieństwie do braku ciał) jest to, że PEVerify może działać i przekazywać (w ten sposób weryfikowanie kompletności metadanych).
Odwołania do zestawów dodatkowo usuwają metadane (składowe prywatne) z zestawów tylko metadanych:
- Zestaw referencyjny zawiera tylko odwołania do tego, czego potrzebuje na powierzchni interfejsu API. Rzeczywisty zestaw może zawierać dodatkowe odwołania związane z konkretnymi implementacjami. Na przykład zestaw referencyjny dla
class C { private void M() { dynamic d = 1; ... } }
elementu nie odwołuje się do żadnych typów wymaganych dla elementudynamic
. - Prywatne elementy członkowskie funkcji (metody, właściwości i zdarzenia) są usuwane w przypadkach, gdy ich usunięcie nie ma zauważalnego wpływu na kompilację. Jeśli nie ma atrybutów InternalsVisibleTo , wewnętrzne elementy członkowskie funkcji również zostaną usunięte.
Metadane w zestawach referencyjnych nadal przechowują następujące informacje:
- Wszystkie typy, w tym typy prywatne i zagnieżdżone.
- Wszystkie atrybuty, nawet te wewnętrzne.
- Wszystkie metody wirtualne.
- Jawne implementacje interfejsu.
- Jawnie zaimplementowane właściwości i zdarzenia, ponieważ ich metody dostępu są wirtualne.
- Wszystkie pola struktur.
Zestawy referencyjne zawierają atrybut ReferenceAssembly na poziomie zestawu. Ten atrybut może być określony w źródle; wówczas kompilator nie będzie musiał go syntetyzować. Ze względu na ten atrybut środowiska uruchomieniowe odmówią załadowania zestawów odwołań do wykonania (ale mogą być ładowane w trybie tylko odbicia).
Dokładne szczegóły struktury zestawu referencyjnego zależą od wersji kompilatora. Nowsze wersje mogą wykluczyć więcej metadanych, jeśli nie ma to wpływu na publiczną powierzchnię interfejsu API.
Uwaga
Informacje w tej sekcji mają zastosowanie tylko do odwołań do zestawów generowanych przez kompilatory Roslyn, począwszy od języka C# w wersji 7.1 lub Visual Basic w wersji 15.3. Struktura zestawów referencyjnych dla bibliotek .NET Framework i .NET Core może się różnić w pewnych szczegółach, ponieważ używają własnego mechanizmu generowania zestawów odwołań. Na przykład mogą mieć całkowicie puste ciała metody zamiast throw null
treści. Jednak ogólna zasada nadal ma zastosowanie: nie mają implementacji metod do użycia i zawierają metadane tylko dla elementów członkowskich, które mają zauważalny wpływ z perspektywy publicznego interfejsu API.