Новые механизмы абстракции
После рассмотрения методов исследования типов (методов рефлексии), встает вопрос – "Какое новое качество могут принести методы рефлексии в программы. Дают ли они в руки разработчика принципиально новые возможности?" Ответ на этот вопрос положительный.
Следует напомнить, что в С++ (а может и во всей идеологии ООП) существуют два принципиально разных подхода к разработке абстрактных алгоритмов и абстрактных типов данных. Первый подход основан на использовании шаблонов, а второй – на наследовании и виртуальных методах.
Формулируя алгоритм с помощью абстрактных типов данных (шаблонов), программист предполагает наличие определённых свойств у параметров шаблона – типов, которые будут "подставлены" в шаблон. Конкретная реализация алгоритма становится ясной тогда, когда становятся известны типы-параметры шаблона, т.е. во время компиляции программы, использующей шаблон – конкретизация при компиляции.
Формулируя алгоритм с помощью абстрактных (виртуальных) методов класса, разработчик откладывает окончательную реализацию алгоритма на время исполнения программы. Именно тогда, во время исполнения, решается то, какие реальные методы будут участвовать в работе алгоритма. Это зависит от того с какими конкретными объектами придётся работать алгоритму. Можно сказать, что виртуальные методы конкретизируются в runtime – конкретизация времени исполнения.
Однако возможность по виртуализации методов классов и их конкретизация во времени исполнения программы делает естественным желание получить то же и по отношению к полям объектов и к абстрактным структурам данных, когда они конкретизируются не при компиляции, а во время исполнения.
Всё это позволяет сделать Reflection. Таким образом, Reflection – это виртуализация всех элементов программы.
Теперь разработчику позволительно формулировать алгоритмы подобные таким:
1. "Найди в данной структуре поле, обозначающее цену товара, и вернуть его". Для этого перебираем все поля класса, в поисках поля типа Currency. Для этого даже не надо знать имя поля. Если известно, что поле такого типа есть и оно одно – этого достаточно.
2. "Связать поля данной структуры с аргументами требуемой хранимой процедуры на основе типов и имён полей и параметров".
3. "Вывести на консоль поля c атрибутом "видимый" (см. пример выше).
4. "Предложить пользователю выбрать класс, заполнить параметры его конструктора класса и создать экземпляр этого класса".
Таким образом, разработчику стало доступно то, что раньше мог делать только компилятор. Эти новые возможности позволяют породить совершенно новые классы алгоритмов, новые подходы к программированию, что, в свою очередь, принесёт новое качество в ваши программы.
Динамическое создание типов
Это ещё один приём программирования в среде .NET, тесно связанный с метаданными, и сулящий не менее революционные изменения в методах программирования.
Динамическое создание программного кода
Иногда требуется динамически создать некий программный код, например класс или перечисление. Естественно, что этот код будет храниться в некоторой сборке. При этом сама динамически созданная сборка может существовать только в памяти или же может быть сохранена на диске в виде файла.
Порядок создания соответствующих объектов программного кода следующий:
1. Сгенерировать сборку;
2. На основе этой сборки сгенерировать модуль;
3. На основе этого модуля сгенерировать тип (например, класс);
4. На основе этого типа (класса) сгенерировать его члены (конструкторы, методы и т.п.);
5. Выполнить непосредственное создание типа.
Ниже приведены два примера создания динамического кода – класса и перечисления.