Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

}

На следующем шаге создается файл проекта. Создайте файл по имени

RoundTrip.ilproj
и приведите его содержимое к следующему виду:

<Project Sdk="Microsoft.NET.Sdk.IL">

<PropertyGroup>

<OutputType>Exe</OutputType>

<TargetFramework>net5.0</TargetFramework>

<MicrosoftNetCoreIlasmPackageVersion>

5.0.0-preview.1.20120.5

</
MicrosoftNetCoreIlasmPackageVersion>

<ProduceReferenceAssembly>false</ProduceReferenceAssembly>

</PropertyGroup>

</Project>

Наконец,

скопируйте созданный файл
RoundTrip.il
в каталог проекта. Скомпилируйте сборку с применением .NET Core CLI:

dotnet build

Результирующие файлы будут находиться, как обычно, в подкаталоге

bin\debug\net5.0
. На этом этапе новое приложение можно запустить. Разумеется, в окне консоли отобразится обновленное сообщение. Хотя приведенный простой пример не является особенно впечатляющим, он иллюстрирует один из сценариев применения возвратного проектирования на CIL.

Директивы и атрибуты CIL

Теперь, когда вы знаете, как преобразовывать сборки .NET Core в файлы

*.il
и компилировать файлы
*.il
в сборки, можете переходить к более детальному исследованию синтаксиса и семантики языка CIL. В последующих разделах будет поэтапно рассматриваться процесс создания специального пространства имен, содержащего набор типов. Тем не менее, для простоты типы пока не будут иметь логики реализации своих членов. Разобравшись с созданием простых типов, можете переключить внимание на процесс определения "реальных" членов с использованием кодов операций CIL.

Указание ссылок на внешние сборки в CIL

Скопируйте файлы

global.json
и
NuGet.config
из предыдущего примера в новый каталог проекта. Создайте новый файл проекта по имени
CILTypes.ilproj
, содержимое которого показано ниже:

<Project Sdk="Microsoft.NET.Sdk.IL">

<PropertyGroup>

<TargetFramework>net5.0</TargetFramework>

<MicrosoftNetCoreIlasmPackageVersion>

5.0.0-preview.1.20120.5

</MicrosoftNetCoreIlasmPackageVersion>

<ProduceReferenceAssembly>false</ProduceReferenceAssembly>

</PropertyGroup>

</Project>

Затем создайте в текстовом редакторе новый файл по имени

CILTypes.il
. Первой задачей в проекте CIL является перечисление внешних сборок, которые будут задействованы текущей сборкой. В рассматриваемом примере применяются только типы, находящиеся внутри сборки
System.Runtime.dll
. В новом файле понадобится указать директиву
.assembly
с уточняющим атрибутом
external
. При добавлении ссылки на сборку со строгим именем, подобную
System.Runtime.dll
, также должны быть указаны директивы
.publickeytoken
и
.ver
:

.assembly extern System.Runtime

{

.publickeytoken = (B0 3F 5F 7F 11 D5 0A 3A )

.ver 5:0:0:0

}

Определение

текущей сборки в CIL

Следующее действие заключается в определении создаваемой сборки с использованием директивы

.assembly
. В простейшем случае сборка может быть определена за счет указания дружественного имени двоичного файла:

// Наша сборка.

.assembly CILTypes{}

Хотя такой код действительно определяет новую сборку .NET Core, обычно внутрь объявления будут помещаться дополнительные директивы. В рассматриваемом примере определение сборки необходимо снабдить номером версии 1.0.0.0 посредством директивы

.ver
(обратите внимание, что числа в номере версии отделяются друг от друга двоеточиями, а не точками, как принято в С#):

// Наша сборка.

.assembly CILTypes

{

.ver 1:0:0:0

}

Из-за того, что сборка

CILTypes
является однофайловой, ее определение завершается с применением следующей директивы
.module
, которая обозначает официальное имя двоичного файла .NET Core, т.е.
CILTypes.dll
:

// Наша сборка

.assembly CILTypes

{

.ver 1:0:0:0

}

// Модуль нашей однофайловой сборки.

.module CILTypes.dll

Кроме

.assembly
и
.module
существуют директивы CIL, которые позволяют дополнительно уточнять общую структуру создаваемого двоичного файла .NET Core. В табл. 19.1 перечислены некоторые наиболее распространенные директивы уровня сборки.

Определение пространств имен в CIL

Определив внешний вид и поведение сборки (а также обязательные внешние ссылки), вы можете создать пространство имен .NET Core (

MyNamespace
), используя директиву
.namespace
:

// Наша сборка имеет единственное пространство имен.

.namespace MyNamespace {}

Подобно C# определения пространств имен CIL могут быть вложены в другие пространства имен. Хотя здесь нет нужды определять корневое пространство имен, ради интереса посмотрим, как создать корневое пространство имен

MyCompany
:

.namespace MyCompany

{

.namespace MyNamespace {}

}

Как и С#, язык CIL позволяет определить вложенное пространство имен следующим образом:

// Определение вложенного пространства имен.

.namespace MyCompany.MyNamespace {}

Определение типов классов в CIL

Поделиться с друзьями: