Литмир - Электронная Библиотека
A
A

Указание ссылок на внешние сборки в 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
. В простейшем случае сборка может быть определена за счет указания дружественного имени двоичного файла:

<b>// Наша сборка.</b>

.assembly CILTypes{}

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

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

<b>// Наша сборка.</b>

.assembly CILTypes

{

<b>  .ver 1:0:0:0</b>

}

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

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

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

.assembly CILTypes

{

  .ver 1:0:0:0

}

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

.module CILTypes.dll

Кроме

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

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

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

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

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

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

.namespace MyNamespace {}

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

MyCompany
:

.namespace MyCompany

{

  .namespace MyNamespace {}

}

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

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

.namespace MyCompany.MyNamespace {}

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

Пустые пространства имен не особо интересны, поэтому давайте рассмотрим процесс определения типов классов в CIL. Для определения нового типа класса предназначена директива

.class
. Тем не менее, эта простая директива может быть декорирована многочисленными дополнительными атрибутами, уточняющими природу типа. В целях иллюстрации добавим в наше пространство имен открытый класс под названием
MyBaseClass
. Как и в С#, если базовый класс явно не указан, то тип автоматически становится производным от
System.Object
:

.namespace MyNamespace

{

<b>  // Предполагается базовый класс System.Object.</b>

  .class public MyBaseClass {}

}

При построении типа, производного не от класса

System.Object
, применяется атрибут
extends
. Для ссылки на тип, определенный внутри той же самой сборки, язык CIL требует использования полностью заданного имени (однако если базовый тип находится внутри той же самой сборки, то префикс в виде дружественного имени сборки можно не указывать). Следовательно, демонстрируемая ниже попытка расширения
MyBaseClass
в результате дает ошибку на этапе компиляции:

350
{"b":"847442","o":1}