Поделиться через


Эталонные сборки

Эталонные сборки — это специальный тип сборки, содержащей только минимальный объем метаданных, необходимых для представления общедоступной области API библиотеки. Такие сборки включают объявления всех членов, которые имеют значение при ссылке на сборку в инструментах сборки, но исключают все реализации членов и объявления приватных членов, не оказывающих видимого влияния на их API-контракт. Напротив, обычные сборки называются сборками реализации.

Ссылочные сборки не могут быть загружены для выполнения, но их можно передать в качестве входных данных компилятора так же, как сборки реализации. Эталонные сборки обычно распределяются с помощью пакета SDK для определенной платформы или библиотеки.

Использование эталонной сборки позволяет разработчикам создавать программы, предназначенные для конкретной версии библиотеки без полной сборки реализации для этой версии. Предположим, у вас есть только последняя версия некоторых библиотек на компьютере, но вы хотите создать программу, предназначенную для более ранней версии этой библиотеки. При компиляции непосредственно с использованием сборки реализации может получиться так, что вы будете использовать члены API, которые недоступны в более ранней версии. Вы обнаружите эту ошибку только при тестировании программы на целевом компьютере. Если вы компилируете эталонную сборку для более ранней версии, вы сразу же получите ошибку во время компиляции.

Эталонная сборка также может представлять контракт, то есть набор API, которые не соответствуют конкретной сборке реализации. Такие эталонные сборки, называемые сборкой контракта, можно использовать для нескольких целевых платформ, поддерживающих один и тот же набор API. Например, .NET Standard предоставляет сборку контракта netstandard.dll, которая представляет набор общих API, общих для разных платформ .NET. Реализации этих API содержатся в разных сборках на разных платформах, таких как mscorlib.dll в .NET Framework или System.Private.CoreLib.dll в .NET Core. Библиотека, предназначенная для .NET Standard, может работать на всех платформах, поддерживающих .NET Standard.

Использование ссылочных сборок

Чтобы использовать определенные API из проекта, необходимо добавить ссылки на их сборки. Вы можете добавлять ссылки как на сборки реализации, так и на сборки ссылок. Рекомендуется использовать эталонные сборки всякий раз, когда они доступны. Это гарантирует, что вы используете только поддерживаемые члены API в целевой версии, предназначенные для использования конструкторами API. Использование эталонной сборки гарантирует, что вы не зависите от деталей реализации.

Эталонные сборки для библиотек .NET Framework поставляются с таргетирующими пакетами. Их можно получить, скачав автономный установщик или выбрав компонент в установщике Visual Studio. Дополнительные сведения см. в разделе "Установка .NET Framework для разработчиков". Для .NET Core и .NET Standard эталонные сборки автоматически загружаются по мере необходимости (через NuGet) и ссылаются. Для .NET Core 3.0 и более поздних версий эталонные сборки для основной платформы находятся в пакете Microsoft.NETCore.App.Ref (пакет Microsoft.NETCore.App используется вместо версий до 3.0).

При добавлении ссылок на сборки .NET Framework в Visual Studio с помощью диалогового окна "Добавление ссылки " вы выбираете сборку из списка, а Visual Studio автоматически находит эталонные сборки, соответствующие целевой версии платформы, выбранной в проекте. То же самое относится к добавлению ссылок непосредственно в проект MSBuild с помощью элемента эталонного проекта : необходимо указать только имя сборки, а не полный путь к файлу. При добавлении ссылок на эти сборки в командной строке с помощью -reference параметра компилятора (в C# и Visual Basic) или с помощью Compilation.AddReferences метода в API Roslyn необходимо вручную указать справочные файлы сборок для правильной целевой версии платформы. Файлы эталонных сборок .NET Framework находятся в каталоге %ProgramFiles(x86)%\Reference Assemblies\Microsoft\Framework\.NETFramework. Для .NET Core можно принудительно выполнить операцию публикации для копирования ссылочных сборок для целевой платформы в подкаталог публикации и ссылки в выходной PreserveCompilationContext каталог, задав для свойства проекта значение true. Затем вы можете передать эти справочные файлы сборки компилятору. Использование DependencyContext из пакета Microsoft.Extensions.DependencyModel может помочь в нахождении их путей.

Так как они не содержат реализации, ссылочные сборки не могут быть загружены для выполнения. Попытка сделать это приводит к System.BadImageFormatException. Если вы хотите проверить содержимое эталонной сборки, ее можно загрузить в контекст только для рефлексии в .NET Framework (с помощью метода Assembly.ReflectionOnlyLoad) или в контекст MetadataLoadContext в .NET и .NET Framework.

Создание ссылочных сборок

Создание ссылочных сборок для библиотек может быть полезным, если потребители библиотеки должны создавать свои программы на основе множества различных версий библиотеки. Распространение сборок реализации для всех этих версий может быть непрактичным из-за их большого размера. Эталонные сборки меньше размера, а распространение их в составе пакета SDK библиотеки сокращает размер загрузки и экономит место на диске.

Средства разработки и среды разработки также могут использовать справочные сборки для уменьшения времени сборки в случае больших решений, состоящих из нескольких библиотек классов. Как правило, при добавочных сценариях сборки проект перестраивается при изменении любого входного файла, включая сборки, от которых она зависит. Сборка реализации изменяется всякий раз, когда программист изменяет реализацию любого члена. Эталонная сборка изменяется только в том случае, если затронут её публичный API. Таким образом, использование эталонной сборки в качестве входного файла вместо сборки реализации позволяет пропустить сборку зависимого проекта в некоторых случаях.

Вы можете создать эталонные сборки:

Если вы хотите распространять ссылочные сборки с пакетами NuGet, необходимо включить их в подкаталог ref\ в каталог пакета, а не в подкаталог lib\, используемый для сборок реализации.

Структура ссылочных сборок

Эталонные сборки являются расширением связанной концепции сборок только метаданных. Сборки только для метаданных имеют свои тела методов замененные одним телом throw null, но включают все члены, кроме анонимных типов. Причина использования throw null тела (в отличие от отсутствия тел) заключается в том, чтобы PEVerify мог выполняться и успешно завершаться (таким образом проверяя полноту метаданных).

Ссылочные сборки дополнительно удаляют метаданные (частные члены) из сборок, доступных только для метаданных:

  • Эталонная сборка содержит только те ссылки, которые требуются для работы с surface API. Реальная сборка может иметь дополнительные ссылки, связанные с конкретными реализациями. Например, эталонная сборка для class C { private void M() { dynamic d = 1; ... } } не ссылается на какие-либо типы, необходимые для dynamic.
  • Частные члены функции (методы, свойства и события) удаляются в случаях, когда их удаление не заметно влияет на компиляцию. Если атрибуты InternalsVisibleTo отсутствуют, внутренние члены функции также удаляются.

Метаданные в ссылочных сборках продолжают хранить следующие сведения:

  • Все типы, включая частные и вложенные типы.
  • Все атрибуты, даже внутренние.
  • Все виртуальные методы.
  • Явные реализации интерфейса.
  • Явно реализованы свойства и события, так как их методы доступа являются виртуальными.
  • Все поля структур.

Ссылочные сборки включают в себя атрибут уровня сборки ReferenceAssembly. Этот атрибут может быть указан в источнике; затем компилятору не нужно синтезировать его. Из-за этого атрибута среды выполнения откажутся загружать эталонные сборки для выполнения (но их можно загрузить в режиме только отражения).

Точные сведения о структуре эталонной сборки зависят от версии компилятора. Более новые версии могут исключить дополнительные метаданные, если они определены как не влияющие на общедоступную область API.

Замечание

Сведения в этом разделе применимы только к эталонным сборкам, созданным компиляторами Roslyn начиная с C# версии 7.1 или Visual Basic версии 15.3. Структура ссылочных сборок для библиотек .NET Framework и .NET Core может отличаться в некоторых деталях, так как они используют собственный механизм создания ссылочных сборок. Например, они могут иметь полностью пустые тела методов вместо throw null тела. Но общий принцип по-прежнему применяется: они не имеют доступных для использования реализаций методов и содержат метаданные только для членов, которые имеют наблюдаемое влияние с точки зрения общедоступного API.

См. также