История обновлений: №1
Время обновления: 2001-11-01 20:09
Обновлено: Musicwind®
Примечание к обновлению: первый черновой вариант завершен.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~
краткое содержание:
В этой статье обсуждается, как экспортировать классы в Dll — множество подклассов, основанных на определенном абстрактном классе. Эта технология использует идею полиморфизма, позволяющую получать эффекты, аналогичные плагинам.
Предполагаемые читатели:
Понять концепцию полиморфизма; понять концепцию метакласса.
Техническая сложность:
6/10 .
Чтобы экспортировать класс из Dll, первое, о чем вам нужно подумать, — это использовать пакет bpl. Одним из недостатков этого метода является то, что пользователь должен знать, какие классы содержатся в пакете, а это значит, что должно быть известно имя класса — это в определенном смысле ограничение. Представьте себе ситуацию, когда пользователь определяет нижний уровень. абстрактный класс, а затем множество классов приложений (конкретные class), то пользователь надеется, что сможет использовать эти классы, не зная конкретных классов - это кажется немного загадочным, но реальная ситуация действительно такова, потому что ее нельзя предсказать при определении абстрактного класса. классы Сколько конкретных классов будет в будущем? Какие же технологии понадобятся для реализации такого спроса?
На самом деле техническая сложность его реализации не очень сложна - автор здесь посвящает всем свой практический опыт, как способ привлечения новых идей, и надеется увидеть другие, лучшие методы!
Ниже сначала представлены некоторые базовые знания, связанные с этим методом, а затем используется пример, иллюстрирующий конкретную реализацию.
1. Основные понятия
Метакласс (метакласс), также называемый типом ссылки на класс (тип ссылки на класс), можно рассматривать как тип класса, а значение переменной, объявленной с этим типом, представляет собой класс. например:
тип
TClass = Класс TObject;
Это объявляет тип метакласса. Тогда вы можете иметь объявления переменных следующим образом:
Вар
АКласс: ТКласс;
Затем вы можете использовать его следующим образом:
Класс := TObject;
или:
AClass := TButton;
или:
АКласс:= TForm;
и т. д.
Поскольку TClass является метаклассом типа TObject, а TButton, TForm и т. д. являются производными от TObject, такие значения, как TButton и TForm, приемлемы для AClass.
Затем мы можем использовать идею полиморфизма и гибко использовать переменную класса AClass. Это также базовые знания для конкретной реализации, приведенной ниже.
2. Конкретная реализация
Первым шагом является создание абстрактного класса:
Мы используем такое простое объявление. Абстрактный класс предоставляет только абстрактный метод, но это не влияет на наше описание проблемы:
TMyBaseForm = Класс (TForm)
Защищено
функция GetTitle: pchar виртуальный;
конец;
MyBaseFormClass = Класс TMyBaseForm;
Давайте не будем обсуждать, сколько практических методов и интерфейсов предоставляет такой абстрактный класс, потому что мы хотим обсудить техническую осуществимость. Предположим, что первоначальное намерение автора при определении этого интерфейса — получить любое количество изменяющихся заголовков, а конкретное возвращаемое значение GetTitle должно быть реализовано с помощью подклассов. Более того, автор также надеется, что код подкласса можно будет реализовать в Dll и отделить от основной программы - этот метод имеет разновидность плагина, а также, возможно, сможет реализовать некоторые возможности Plug&Play - не правда ли? привлекательный? Итак, что вам делать дальше?
Во-первых, основная программа и программа Dll должны включать в себя объявленные выше модули. Затем основная программа отвечает за реализацию драйвера — динамическую загрузку Dll и динамическую загрузку классов, а Dll отвечает за реализацию подклассов.
Давайте сначала поговорим о Dll. Что должна делать Dll?
Второй шаг — экспортировать подкласс в Dll :
Мы разработали следующие две экспортированные функции:
1. функция GetClassCount: целое число;
Сообщите вызывающему абоненту, что в этой Dll есть несколько подклассов;
2. функция GetClassTypeByIndex (const iIndex: целое число;
вар ClassType: MyBaseFormClass): WordBool;
Получить конкретный подкласс по индексу. Обратите внимание, что тип ClassType здесь — MyBaseFormClass, что указывает на то, что его значением будет определенный класс, унаследованный от TMyBaseForm.
Вот одна из возможных их реализаций:
функция GetClassCount: целое число;
начинать
result := 3 //Указывает, что в этой Dll экспортировано 3 класса
конец;
функция GetClassTypeByIndex (const iIndex: целое число;
вар ClassType: MyBaseFormClass): WordBool;
начинать
результат := Истина;
случай iIndex of
0: Тип Класса: = TFrmTest1;
1: ТипКласса:= TFrmTest2;
2: ТипКласса:= TFrmTest3;
еще
результат := Ложь;
конец;
конец;
Разумеется, модули, на которых расположены TFrmTest1, TFrmTest2 и TFrmTest3, должны быть включены в список использования модуля. Реализация TFrmTest1 может быть такой:
TFrmTest1 = Класс (TMyBaseForm)
защищенный
функция GetTitle: PChar переопределить;
конец;
функция TFrmTest1.GetTitle: Pchar;
начинать
результат := 'Привет от TFrmTest1';
конец;
Наконец, не забудьте добавить GetClassCount и GetClassByIndex в список экспорта. Затем при создании проекта Dll установите флажок «использовать пакет времени выполнения» в пакете параметров проекта. Конкретные причины будут обсуждаться позже.
На этом работа над Dll подошла к концу.
Третий шаг — реализация основного программного драйверного движка:
Этот шаг относительно прост — это не что иное, как динамическая загрузка Dll, затем вызов функции GetClassCount и затем вызов GetClassByIndex. Ключевой код:
Вар AClass: TMyBaseClass;
Форма: TMyBaseForm;
Я, iCount: целое число;
blResult: Boolean;
начинать
//Опускаем часть о загрузке динамической библиотеки, предполагая, что FPGetClassProc указывает на функцию GetClassCount, а FPGetClassByIndexProc указывает на GetClassByIndex, тогда:
iCount: = FPGetClassProc;
для I := 0 до iCount ?C 1 делать
начинать
AClass := FPGetClassByIndex(I, blResult);
если blResult тогда
начинать
AForm := AClass.Create(приложение);
AForm.Caption := AForm.GetTitle;
Форма.Показать;
конец;
конец;
//…
конец;
Обратите внимание, что, как и в случае с Dll, вам также необходимо выбрать использование пакета времени выполнения при создании выходного файла. Это связано с тем, что неиспользование пакета среды выполнения приведет к появлению в памяти нескольких копий одного и того же класса, поэтому использование для них оператора Is вернет результат False.
Musicwind®@HangZhou.Zhejiang.China
01.11.2001
Еще статьи
[ Конец статьи]