Язык программирования C#9 и платформа .NET5 - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
.ver 5:0:0:0
}
.assembly extern System.Console
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.ver 5:0:0:0
}
Каждый блок .assembly extern уточняется директивами .publickeytoken и .ver. Инструкция .publickeytoken присутствует только в случае, если сборка была сконфигурирована со строгим именем. Маркер .ver определяет числовой идентификатор версии ссылаемой сборки.
На заметку! Предшествующие версии .NET Framework в большой степени полагались на назначение строгих имен, которые вовлекали комбинацию открытого и секретного ключей. Это требовалось в среде Windows для сборок, подлежащих добавлению в глобальный кеш сборок, но с выходом .NET Core необходимость в строгих именах значительно снизилась.
После ссылок на внешние сборки вы обнаружите несколько маркеров .custom, которые идентифицируют атрибуты уровня сборки (кроме маркеров, сгенерированных системой, также информацию об авторском праве, название компании, версию сборки и т.д.). Ниже приведена (совсем) небольшая часть этой порции данных манифеста:
.assembly CarLibrary
{
...
.custom instance void ... TargetFrameworkAttribute ...
.custom instance void ... AssemblyCompanyAttribute ...
.custom instance void ... AssemblyConfigurationAttribute ...
.custom instance void ... AssemblyFileVersionAttribute ...
.custom instance void ... AssemblyProductAttribute ...
.custom instance void ... AssemblyTitleAttribute ...
Такие настройки могут устанавливаться либо с применением окна свойств проекта в Visual Studio, либо путем редактирования файла проекта и добавления надлежащих элементов. Находясь в среде Visual Studio, щелкните правой кнопкой мыши на имени проекта в окне Solution Explorer, выберите в контекстном меню пункт Properties (Свойства) и перейдите не вкладку Package (Пакет) в левой части открывшегося диалогового окна (рис. 16.4).
Добавить метаданные к сборке можно и прямо в файле проекта *.csproj. Следующее обновление главного узла PropertyGroup в файле проекта приводит к тому же результату, что и заполнение формы, представленной на рис. 16.4:
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<Copyright>Copyright 2020</Copyright>
<Authors>Phil Japikse</Authors>
<Company>Apress</Company>
<Product>Pro C# 9.0</Product>
<PackageId>CarLibrary</PackageId>
<Description>This is an awesome library for cars.</Description>
<AssemblyVersion>1.0.0.1</AssemblyVersion>
<FileVersion>1.0.0.2</FileVersion>
<Version>1.0.0.3</Version>
</PropertyGroup>
На заметку! Остальные поля информации о сборке на рис. 16.4 (и в показанном выше содержимом файла проекта) используются при генерировании пакетов NuGet из вашей сборки. Данная тема раскрывается позже в главе.
Исследование кода CIL
Вспомните, что сборка не содержит инструкций, специфичных для платформы; взамен в ней хранятся инструкции на независимом от платформы общем промежуточном языке (Common Intermediate Language — CIL). Когда исполняющая среда .NET Core загружает сборку в память, ее внутренний код CIL компилируется (с использованием JIT-компилятора) в инструкции, воспринимаемые целевой платформой. Например, метод TurboBoost() класса SportsCar представлен следующим кодом CIL:
.method public hidebysig virtual
instance void TurboBoost() cil managed
{
.maxstack 8
IL_0000: nop
IL_0001: ldstr "Ramming speed! Faster is better..."
IL_0006: call void [System.Console]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
}
// end of method SportsCar::TurboBoost
Большинству разработчиков приложений .NET Core нет необходимости глубоко погружаться в детали кода CIL. В главе 19 будут приведены дополнительные сведения о синтаксисе и семантике языка CIL, которые могут быть полезны при построении более сложных приложений, требующих расширенных действий вроде конструирования сборок во время выполнения.
Исследование метаданных типов
Прежде чем приступить к созданию приложений, в которых задействована ваша специальная библиотека .NET Core, давайте займемся исследованием метаданных для типов внутри сборки CarLibrary.dll. Скажем, вот определение TypeDef для типа EnginestateEnum:
TypeDef #1 (02000002)
-------------------------------------------------------
TypDefName: CarLibrary.EngineStateEnum
Flags : [Public] [AutoLayout] [Class] [Sealed] [AnsiClass]
Extends : [TypeRef] System.Enum
Field #1
-------------------------------------------------------
Field Name: value__
Flags : [Public] [SpecialName] [RTSpecialName]
CallCnvntn: [FIELD]
Field type: I4
Field #2
-------------------------------------------------------
Field Name: EngineAlive
Flags : [Public] [Static] [Literal] [HasDefault]
DefltValue: (I4) 0
CallCnvntn: [FIELD]
Field type: ValueClass CarLibrary.EngineStateEnum
Field #3
-------------------------------------------------------
Field Name: EngineDead
Flags : [Public] [Static] [Literal] [HasDefault]
DefltValue: (I4) 1
CallCnvntn: [FIELD]
Field type: ValueClass CarLibrary.EngineStateEnum
Как будет объясняться в следующей главе, метаданные сборки являются важным элементом платформы .NET Core и служат основой для многочисленных технологий (сериализация объектов, позднее связывание, расширяемые приложения и т.д.). В любом случае теперь, когда вы заглянули внутрь сборки CarLibrary.dll, можно приступать к построению клиентских приложений, в которых будут применяться типы из сборки.
Построение клиентского приложения C#
Поскольку все типы в CarLibrary были объявлены с ключевым словом public, другие приложения .NET Core имеют возможность пользоваться ими. Вспомните, что типы могут также определяться с применением ключевого слова internal языка C# (на самом деле это стандартный режим доступа в C# для классов). Внутренние типы могут использоваться только в сборке, где они определены. Внешние клиенты не могут ни видеть, ни создавать экземпляры типов, помеченных ключевым словом internal.
На заметку! Исключением из указанного правила является ситуация, когда сборка явно разрешает доступ другой сборке с помощью атрибута InternalsVisibleTo, который вскоре будет рассмотрен.
Чтобы воспользоваться функциональностью вашей библиотеки, создайте в том же решении, где находится CarLibrary, новый проект консольного приложения C# по имени CSharpCarClient. Вы можете добиться цели с применением Visual Studio (щелкнув правой кнопкой мыши на имени решения и выбрав в контекстном меню пункт Add►New Project (Добавить►Новый проект)) или командной строки (ниже показаны три команды, выполняемые по отдельности):
dotnet new console -lang c# -n CSharpCarClient -o .CSharpCarClient -f net5.0
dotnet add CSharpCarClient reference CarLibrary
dotnet sln .Chapter16_AppRojects.sln add .CSharpCarClient
Приведенные команды создают проект консольного приложения, добавляют к нему ссылку на проект CarLibrary и вставляют его в имеющееся решение.
На заметку! Команда add reference создает ссылку на проект, что удобно на этапе разработки, т.к. CSharpCarClient будет всегда использовать последнюю версию CarLibrary. Можно также ссылаться прямо на сборку. Прямые ссылки