// Тип музыкального проигрывателя, установленный в данном автомобиле.
public enum MusicMediaEnum
{
MusicCd,
MusicTape,
MusicRadio,
MusicMp3
}
}
// EngineStateEnum.cs
namespace CarLibrary
{
//
Представляет состояние двигателя.
public enum EngineStateEnum
{
EngineAlive,
EngineDead
}
}
Далее создайте абстрактный базовый класс по имени
Car
, который определяет разнообразные данные состояния через синтаксис автоматических свойств. Класс
Car
также имеет единственный абстрактный метод
TurboBoost
, в котором применяется специальное перечисление (
EngineState
), представляющее текущее состояние двигателя автомобиля. Вставьте в проект новый файл класса C# по имени
Car.cs
со следующим кодом:
namespace CarLibrary
{
// Абстрактный базовый класс в иерархии.
public abstract class Car
{
public string PetName {get; set;}
public int CurrentSpeed {get; set;}
public int MaxSpeed {get; set;}
protected EngineStateEnum State = EngineStateEnum.EngineAlive;
public EngineStateEnum EngineState => State;
public abstract void TurboBoost;
protected Car{}
protected Car(string name, int maxSpeed, int currentSpeed)
{
PetName = name;
MaxSpeed = maxSpeed;
CurrentSpeed = currentSpeed;
}
}
}
Теперь предположим, что есть два непосредственных потомка класса
Car
с именами
MiniVan
(минивэн) и
SportsCar
(спортивный автомобиль). В каждом из них абстрактный метод
TurboBoost
переопределяется для отображения подходящего сообщения в окне консоли. Вставьте в проект два новых файла классов C# с именами
MiniVan.cs
и
SportsCar.cs
. Поместите в них показанный ниже код:
// SportsCar.cs
using System;
namespace CarLibrary
{
public class SportsCar : Car
{
public SportsCar{ }
public SportsCar(
string name, int maxSpeed, int currentSpeed)
: base (name, maxSpeed, currentSpeed){ }
public override void TurboBoost
{
Console.WriteLine("Ramming speed! Faster is better...");
}
}
}
// MiniVan.cs
using System;
namespace CarLibrary
{
public class MiniVan : Car
{
public MiniVan{ }
public MiniVan(
string name, int maxSpeed, int currentSpeed)
: base (name, maxSpeed, currentSpeed){ }
public override void TurboBoost
{
//
Минивэны имеют плохие возможности ускорения!
State = EngineStateEnum.EngineDead;
Console.WriteLine("Eek! Your engine block exploded!");
}
}
}
Исследование манифеста
Перед использованием
CarLibrary.dll
в клиентском приложении давайте посмотрим, как библиотека кода устроена внутри. Предполагая, что проект был скомпилирован, запустите утилиту
ildasm.exe
со скомпилированной сборкой. Если у вас нет утилиты
ildasm.exe
(описанной ранее в книге), то она также находится в каталоге для настоящей главы внутри хранилища GitHub.
ildasm /all /METADATA /out=CarLibrary.il
.\CarLibrary\bin\Debug\net5.0\CarLibrary.dll
Раздел манифеста
Manifest
дизассемблированных результатов начинается со строки
//Metadata version: 4.0.30319
. Непосредственно за ней следует список всех внешних сборок, требуемых для библиотеки классов:
// Metadata version: v4.0.30319
.assembly extern System.Runtime
{
.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )
.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, которые идентифицируют атрибуты уровня сборки (кроме маркеров, сгенерированных системой, также информацию об авторском праве, название компании, версию сборки и т.д.). Ниже приведена (совсем) небольшая часть этой порции данных манифеста: