Книга: ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание

Создание CILCars.dll

Создание CILCars.dll

Первым делом следует построить файл *.dll для использования клиентом. Откройте любой текстовый редактор и создайте новый файл *.il с именем CILCars.il. Этот одномодульный компоновочный блок будет использовать два внешних двоичных файла .NET, поэтому вы можете начать свой файл программного кода CIL так.

// Ссылка на mscorlib.dll и
// System.Windows.Forms.dll
.assemblу extern mscorlib {
 .publickeytoken = (B7 7A 5С 56 19 34 E0 89)
 .ver 2:0:0:0
}
.assembly extern System.Windows.Forms {
 .publickeytoken = (B7 7A 5C 56 19 34 E0 89)
 .ver 2:0:0:0
}
// Определение одномодульного компоновочного блока.
.assembly CILCars {
 .hash algorithm 0х00008004
 .ver 1:0:0:0
}
.modulе СILCars.dll

Как уже было сказано, этот компоновочный блок будет содержать два типа класса. Первый тип, CILCar, определяет два поля данных и пользовательский конструктор. Второй тип, CarInfoHelper, определяет единственный статический метод с именем DisplayCarInfо(), который использует CILCar в качестве параметра и возвращает void. Оба типа находятся в пространстве имен CILCars. В терминах CIL класс CILCar можно реализовать так.

// Реализация типа CILCars.CILCar.
.namespace CILCars {
 .class public auto ansi beforefieldinit CILCar extends [mscorlib]System.Object {
  // Поле данных CILCar.
.field public string petName
  .field public int32 currSpeed
  // Пользовательский конструктор, который дает пользователю
  // возможность присвоить полю данные.
  .method public hidebysig specialname rtspecialname instance void .ctor(int32 c, string p) cil managed {
   .maxstack 8
   // Загрузка первого аргумента в стек и вызов
   // конструктора базового класса.
   ldarg.0 // объект 'this', а не int32!
   call instance void [mscorlib]System.Object::.ctor()
   // Теперь загрузка первого и второго аргументов в стек.
   ldarg.0 // объект 'this'
   ldarg.1 // аргумент int32
   // Сохранение элемента вершины стека (int 32) в поле currSpeed.
   stfld int32 CILCars.CILCar::currSpeed
   // Загрузка строкового аргумента и сохранение в поле petName.
   ldarg.0 // объект 'this'
   ldarg.2 // аргумент string
   stfld string CILCars.CILCar::petName
   ret
  }
 }
}

Имея в виду, что настоящим первым аргументом любого нестатического члена является объектная ссылка this, в первом блоке CIL-кода мы просто загружаем эту объектную ссылку и вызываем конструктор базового класса. Затем поступающие аргументы конструктора помещаются в стек и запоминаются в полях данных типа с помощью кода операции stfld (сохранение в поле).

Далее, вы должны реализовать второй тип в данном пространстве имен, а именно тип CILCarInfo. Суть типа находится в статическом методе Display(). Основной задачей этого метода является получение поступающего параметра CILCar, извлечение значения поля данных и вывод его в окне сообщения Windows Forms. Вот полная реализация CILCarInfo, а далее следует ее анализ.

.class public auto ansi beforefieldinit CILCarInfo extends [mscorlib]System.Object {
 .method public hidebysig static void Display(class CILCars.CILCar c) cil managed {
  .maxstасk 8
  // Нам нужна локальная строковая переменная.
  .locals init ([0] string caption)
  // Загрузка строки и входного CILCar в стек.
  ldstr "Скорость [0]: "
  ldarg.0
  // Помещение значения petName класса CILCar в стек и
  // вызов статического метода String.Format().
  ldfld string CILCars.CILCar::petName
  call string [mscorlib]System.String::Format(string, object)
  stloc.0
  // Загрузка значения поля currSpeed и получение его строкового // представления (обратите внимание на вызов ToString()).
  ldarg.0
  ldflda int32 CILCars.CILCar::currSpeed
  call instance string [mscorlib]System.Int32::ToString()
  ldloc.0
  // Вызов метода MessageBox.Show() с загруженными значениями.
  call valuetype [System.Windows.Forms] System.Windows.Forms.DialogResult [Sуstem.Windоws.Forms] System.Windows.Forms.MessageBox::Show(string, string)
  pop
  ret
 }
}

Хотя здесь объем программного кода CIL заметно больше, чем в случае реализации CILCar, на самом деле все довольно просто. Во-первых, поскольку вы определяете статический метод, вам не придется иметь дел со скрытой объектной ссылкой (поэтому код операции ldarg.0 действительно загружает поступающий аргумент CILCar).

Метод начинается с загрузки строки ("Скорость {0}: ") в стек за которой следует аргумент CILCar. Когда эти два значения оказываются в нужном месте, загружается значение поля petName и вызывается статический метод System.String. Format(), чтобы вместо замещающих фигурных скобок получить имя CILCar.

Та же общая процедура выполняется и при обработке поля currSpeed, но следует отметить, что здесь используется код. операции ldarga, которая загружает адрес аргумента в стек. Затем вызывается System.Int32.ToString(), чтобы преобразовать значение, размещенное по указанному адресу, в строковый тип. Наконец, когда обе строки отформатированы так, как требуется, вызывается метод MessageBox.Show().

Теперь вы можете скомпилировать свой новый файл *.dll с помощью ilasm.exe, используя команду

ilasm /dll CILCars.il

а затем проверить полученный CIL-код с помощью peverifу.exe.

peverify CILCars.dll

Оглавление книги


Генерация: 0.058. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз