Язык программирования C#9 и платформа .NET5 - Троелсен Эндрю
IL_0001: stloc.0 // Сохранить это значение по индексу 0.
IL_0002: br.s IL_000b // Перейти на метку IL_ 0008.
IL_0003: ldloc.0 // Загрузить значение переменной по индексу 0.
IL_0004: ldc.i4.1 // Загрузить значение 1 в стек.
IL_0005: add // Добавить текущее значение в стеке по индексу 0.
IL_0006: stloc.0
IL_0007: ldloc.0 // Загрузить значение по индексу 0.
IL_0008: ldc.i4.s 10 // Загрузить значение 10 в стек.
IL_0009: clt // Меньше значения в стеке?
IL_000a: stloc.1 // Сохранить результат по индексу 1.
IL_000b: ldloc.1 // Загрузить значение переменной по индексу 1.
IL_000c: brtrue.s IL_0002 // Если истинно, тогда перейти на метку IL 0002.
IL_000d: ret
}
Код CIL начинается с определения локальной переменной типа
int32
IL_0008
IL_0004
i
Заключительные слова о языке CIL
Ознакомившись с процессом создания исполняемого файла из файла
*.il
*.il
Существуют также коммерческие инструменты, которые восстанавливают исходный код сборки .NET Core. Если вам доводилось когда-либо пользоваться одним из инструментов подобного рода, то теперь вы знаете, каким образом они работают!
Динамические сборки
Естественно, процесс построения сложных приложений .NET Core на языке CIL будет довольно-таки неблагодарным трудом. С одной стороны, CIL является чрезвычайно выразительным языком программирования, который позволяет взаимодействовать со всеми программными конструкциями, разрешенными CTS. С другой стороны, написание низкоуровневого кода CIL утомительно, сопряжено с большими затратами времени и подвержено ошибкам. Хотя и правда, что знание — сила, вас может интересовать, насколько важно держать в уме все правила синтаксиса CIL. Ответ: зависит от ситуации. Разумеется, в большинстве случаев при программировании приложений .NET Core просматривать, редактировать или писать код CIL не потребуется. Однако знание основ языка CIL означает готовность перейти к исследованию мира динамических сборок (как противоположности статическим сборкам) и роли пространства имен
System.Reflection.Emit
Первым может возникнуть вопрос: чем отличаются статические сборки от динамических? По определению статической сборкой называется двоичная сборка .NET, которая загружается прямо из дискового хранилища, т.е. на момент запроса средой CLR она находится где-то на жестком диске в физическом файле (или в наборе файлов, если сборка многофайловая). Как и можно было предположить, при каждой компиляции исходного кода C# в результате получается статическая сборка.
Что касается динамической сборки, то она создается в памяти на лету с использованием типов из пространства имен
System.Reflection.Emit
System.Reflection.Emit
Несмотря на то что создание динамических сборок является сложной (и редкой) задачей программирования, оно может быть удобным в разнообразных обстоятельствах. Ниже перечислены примеры.
• Вы строите инструмент программирования .NET Core, который должен быть способным генерировать сборки по требованию на основе пользовательского ввода.
• Вы создаете приложение, которое нуждается в генерации посредников для удаленных типов на лету, основываясь на полученных метаданных.
• Вам необходима возможность загрузки статической сборки и динамической вставки в двоичный образ новых типов.
Давайте посмотрим, какие типы доступны в пространстве имен
System.Reflection.Emit
Исследование пространства имен System.Reflection.Emit
Создание динамической сборки требует некоторых знаний кодов операций CIL, но типы из пространства имен
System.Reflection.Emit
TypeBuilder
specialname
rtspecialname
.ctor
ConstructorBuilder
System.Reflection.Emit

В целом типы из пространства имен
System.Reflection.Emit
ILGenerator
Роль типа System.Reflection.Emit.ILGenerator
Роль типа
ILGenerator
ILGenerator
ILGenerator
MethodBuilder
ConstructorBuilder
Вот пример:
// Получить объект ILGenerator из объекта ConstructorBuilder
// по имени myCtorBuilder.