- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
Тип ModuleBuilder является ключевым типом для процесса построения динамических компоновочных блоков. В соответствии с возможными ожиданиями, ModuleBuilder предлагает целый ряд членов, позволяющих определить множество типов, содержащихся в данном модуле (классы, интерфейсы, структуры и т.д.), а также множество встроенных ресурсов (таблицы строк, изображения и т.д.; формат ресурсов .NET будет рассмотрен в главе 20). Некоторые из методов, относящихся к созданию инфраструктуры модуля, описаны в табл. 15.11 (каждый из этих методов возвращает тип, представляющий тот тип, который вы собирались сконструировать).
Таблица 15.11. Подборка членов типа ModuleBuilder
Метод Описание DefineEnum() Используется для генерирования определения перечня .NET DefineResource() Определяет управляемый встроенный ресурс, который должен храниться в данном модуле DefineType() Конструирует TypeBuilder, который позволяет определять типы значений, интерфейсы и типы класса (в том числе и делегаты)Ключевым членом класса ModuleBuilder, о котором следует знать, является DefineType(). Вдобавок к указанию имени типа (в виде простой строки), вы должны использовать перечень System.Reflection.TypeAttributes, чтобы непосредственно описать формат типа. Основные члены перечня TypeAttributes представлены в табл. 15.12.
Таблица 15.12. Подборка элементов перечня TypeAttributes
Член Описание Abstract Указывает абстрактный тип Class Указывает тип класса Interface Указывает тип интерфейса NestedAssembly Указывает, что класс вложен в область видимости компоновочного блока и поэтому доступен только для методов соответствующего компоновочного блока NestedFamAndAssem Указывает, что класс вложен в область видимости семейства и компоновочного блока и поэтому доступен только для методов, принадлежащих пересечению соответствующего семейства и компоновочного блока NestedFamily Указывает, что класс вложен в область видимости семейства и поэтому доступен только для методов соответствующего типа и его подтипов NestedFamORAssem Указывает, что класс вложен в область видимости семейства или компоновочного блока и поэтому доступен только для методов, принадлежащих объединению соответствующего семейства и компоновочного блока NestedPrivate Указывает вложенный класс с приватной областью видимости NestedPublic Указывает вложенный класс с общедоступной областью видимости NotPublic Указывает класс, не являющийся открытым Public Указывает открытый класс Sealed Указывает изолированный класс, который не может быть расширен Serializable Указывает класс, допускающий сериализациюГенерирование типа HelloClass и принадлежащей ему строковой переменной
Теперь вы понимаете роль метода ModuleBuilder.CreateType(), и пришло время выяснить, как сгенерировать открытый тип класса HelloWorld и приватную строковую переменную.
// Определение открытого класса MyAssembly.HelloWorld.
TypeBuilder helloWorldClass = module.DefineType("MyAssembly.HelloWorld", TypeAttributes.Public);
// Определение принадлежащей классу приватной переменной String
// с именем theMessage.
FieldBuilder msgField =hellоWоrldclass.DefineField("theMessage", typeof(string), FieldAttributes.Private);
Обратите внимание на то, что метод TypeBuilder.DefineField() обеспечивает доступ к типу FieldBuilder. Класс TypeBuilder определяет также другие методы, обеспечивающие доступ к другим типам "построителя". Например, DefineConstructor() возвращает ConstructorBuilder.DefineProperty() – PropertyBuilder и т.д.
Генерирование конструкторов
Как уже упоминалось выше, для определения конструктора типа может использоваться метод TypeBuilder.DefineConstructor(). Однако в нашей реализации конструктора HelloClass, чтобы назначить поступающий параметр внутренней приватной строке, мы добавим CIL-код в тело конструктора непосредственно. Чтобы получить тип ILGenerator, вызывается метод GetILGenerator() соответствующего типа "построителя", на который имеется ссылка (в данном случае это тип ConstructorBuilder).
Метод Emit() класса ILGenerator отвечает за размещение CIL-кода в реализации члена. Сам метод Emit() часто использует тип класса OpCodes, который с помощью полей, доступных только для чтения, открывает доступ к набору кодов операций CIL. Например, OpCodes.Ret указывает возврат вызова метода, OpCodes.Stfld выполняет присваивание значения члену-переменной, a OpCodes.Call используется для вызова метода (в нашем случае это конструктор базового класса). С учетом сказанного рассмотрите следующую программную логику конструктора.
// Создание пользовательского конструктора, имеющего
// один аргумент System.String.
Type[] constructorArgs = new Type[1];
constructorArgs[0] = typeof(string);
ConstructorBuilder constructor = helloWorldClass.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, constructorArgs);
// Теперь в конструктор добавляется необходимый CIL-код.
ILGenerator constructorIL = constructor.GеtILGenerator();
constructorIL.Emit(OpCodes.Ldarg_0);
Type objectClass = typeof(object);
ConstructorInfo superConstructor = objectClass.GetConstructor(new Type[0]);
constructorIL.Emit(OpCodes.Call, superConstructor); // Вызов конструктора базового класса.
// Загрузка указателя 'this' объекта в стек.
constructorIL.Emit(OpCodes.Ldarg_0);
// Загрузка входного аргументе в стек и сохранения в msgField.
constructorIL.Emit(Opcodes.Ldarg_1);
constructorIL.Emit(Opcodes.Stfld, msgField); // Присвоение msgField.
constructorIL.Emit(Opcodes.Ret); // Возврат.
Вы, конечно, хорошо знаете, что как только для типа определяется пользовательский конструктор, конструктор, заданный по умолчанию, автоматически "отключается". Чтобы переопределить конструктор, не имеющий аргументов, просто вызовите метод DefineDefaultConstructor() типа TypeBuilder, как показано ниже.
// Восстановление конструктора, заданного по умолчанию.
helloWorldClass.DefineDefaultConstructor(MethodAttributes.Public);
Следующий вызов порождает стандартный CIL-код для определения конструктора, заданного по умолчанию.
.method public hidebysig specialname rtspecialname instance void .ctor() cil managed {
.maxstack 1
ldarg.0
call instance void [mscorlib]System.Object::.ctor()
ret
}
Генерирование метода HelloWorld()
Наконец, рассмотрим задачу генерирования метода SayHello(). Первой задачей здесь оказывается получение типа MethodBuilder из переменной helloWorld-Class. После этого определяется указанный метод и получается ILGenerator, позволяющий добавить соответствующие CIL-инструкции.
// Создание метода SayHello.
MethodBuilder sayHiMethod = helloWorldClass.DefineMethod("SayHello", MethodAttributes.Public, null, null);
methodIL = sayHiMethod.GetILGenerator();
// Вывод на консоль.
methodIL.EmitWriteLine("Всем привет!");
methodIL.Emit(Opcodes.Ret);
Здесь создается открытый метод (MethodAttributes.Public), не имеющий параметров и не возвращающий ничего (на это указывают значения null в вызове DefineMethod()). Также обратите внимание на вызов EmitWriteLine(). Этот вспомогательный член класса ILGenerator автоматически записывает строку в стандартный поток вывода.
Использование динамически сгенерированного компоновочного блока
Теперь, когда имеется вся программная логика, позволяющая создать и сохранить компоновочный блок, нужен класс для запуска этой логики. Для того чтобы замкнуть цикл, предположим, что в проекте определен второй класс, названный AsmReader. С помощью метода Thread.GetDomain() в Main() получается доступ к текущему домену приложения, который используется для принятия динамически создаваемого компоновочного блока. Получив соответствующую ссылку, вы можете вызвать метод CreateMyAsm().