Update-Verlauf: Nr. 1
Aktualisierungszeit: 01.11.2001 20:09
Aktualisiert von: Musicwind®
Update-Hinweis: Erster Entwurf abgeschlossen.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~ ~~~~~~~~~~~~~~~~~~~~~
Zusammenfassung:
In diesem Artikel wird erläutert, wie Klassen in eine DLL exportiert werden – viele Unterklassen basierend auf einer bestimmten abstrakten Klasse. Diese Technologie nutzt die Idee des Polymorphismus und ermöglicht es uns, Plug-In-ähnliche Effekte zu erzielen.
Zielgruppe:
Verstehen Sie das Konzept des Polymorphismus; verstehen Sie das Konzept der Metaklasse.
Technische Schwierigkeit:
6/10 .
Um eine Klasse aus einer DLL zu exportieren, müssen Sie zunächst daran denken, das BPL-Paket zu verwenden. Ein Nachteil dieser Methode besteht darin, dass der Benutzer wissen muss, welche Klassen im Paket enthalten sind, was bedeutet, dass der Name der Klasse bekannt sein muss – dies stellt in gewissem Sinne eine Einschränkung dar. Stellen Sie sich eine Situation vor, in der der Benutzer eine unterste Ebene definiert abstrakte Klasse und dann viele Anwendungsklassen (concrete Klasse), dann hofft der Benutzer, diese Klassen verwenden zu können, ohne die spezifischen Klassen zu kennen - es scheint ein wenig mysteriös, dies zu sagen, aber die tatsächliche Situation ist wahr, da sie bei der Definition abstrakter Klassen nicht vorhergesagt werden kann Wird es in Zukunft viele spezifische Klassen geben? Welche Art von Technologie wird also benötigt, um eine solche Nachfrage zu realisieren?
Tatsächlich ist die technische Schwierigkeit der Implementierung nicht sehr schwierig – der Autor widmet hier seine praktische Erfahrung allen, um neue Ideen anzulocken, und hofft, andere bessere Methoden zu sehen!
Im Folgenden werden zunächst einige Grundkenntnisse dieser Methode vorgestellt und anschließend anhand eines Beispiels die konkrete Implementierung veranschaulicht.
1. Grundkonzepte
Die Metaklasse (Metaklasse), auch Klassenreferenztyp (Klassenreferenztyp) genannt, kann als Klassentyp betrachtet werden, und der Wert einer mit diesem Typ deklarierten Variablen stellt eine Klasse dar. Zum Beispiel:
Typ
TClass = Klasse von TObject;
Dies deklariert einen Metaklassentyp. Dann können Sie Variablendeklarationen wie diese haben:
Var
AKlasse: TKlasse;
Dann können Sie es wie folgt verwenden:
AClass := TObject;
oder:
AClass := TButton;
oder:
AClass := TForm;
usw.
Da TClass eine Metaklasse vom Typ TObject ist und TButton, TForm usw. alle von TObject abgeleitet sind, sind Werte wie TButton und TForm für AClass akzeptabel.
Dann können wir die Idee des Polymorphismus nutzen und die Klassenvariable AClass flexibel verwenden. Dies ist auch das Grundwissen für die konkrete Implementierung weiter unten.
2. Konkrete Umsetzung
Der erste Schritt besteht darin, eine abstrakte Klasse zu erstellen:
Wir verwenden eine solche einfache Deklaration. Die abstrakte Klasse stellt nur eine abstrakte Methode bereit, hat jedoch keinen Einfluss auf unsere Beschreibung des Problems:
TMyBaseForm = Klasse(TForm)
Geschützt
Funktion GetTitle: pchar; virtual;
Ende;
MyBaseFormClass = Klasse von TMyBaseForm;
Lassen Sie uns nicht diskutieren, wie viele praktische Methoden und Schnittstellen eine solche abstrakte Klasse bietet, denn wir wollen die technische Machbarkeit diskutieren. Angenommen, die ursprüngliche Absicht des Autors bei der Definition dieser Schnittstelle besteht darin, eine beliebige Anzahl sich ändernder Titel zu erhalten, und der spezifische Rückgabewert von GetTitle muss von Unterklassen implementiert werden. Darüber hinaus hofft der Autor auch, dass der Code der Unterklasse in einer DLL implementiert und vom Hauptprogramm getrennt werden kann – diese Methode hat den Flair eines Plug-Ins und kann möglicherweise auch einige Funktionen von Plug&Play realisieren – nicht Ist es nicht ganz attraktiv? Was sollten Sie also als nächstes tun?
Erstens sollten das Hauptprogramm und das DLL-Programm die oben deklarierten Einheiten enthalten. Dann ist das Hauptprogramm für die Implementierung eines Treibers verantwortlich – das dynamische Laden von DLL und das dynamische Laden von Klassen, und DLL ist für die Implementierung von Unterklassen verantwortlich.
Lassen Sie uns zuerst über Dll sprechen. Was soll Dll tun?
Der zweite Schritt besteht darin, die Unterklasse in Dll zu exportieren :
Wir haben die folgenden zwei exportierten Funktionen entworfen:
1. Funktion GetClassCount: integer;
Teilen Sie dem Aufrufer mit, dass es in dieser Dll mehrere Unterklassen gibt;
2. Funktion GetClassTypeByIndex(const iIndex: integer;
var ClassType: MyBaseFormClass): WordBool;
Rufen Sie eine bestimmte Unterklasse anhand des Index ab. Beachten Sie, dass der Typ von ClassType hier MyBaseFormClass ist, was angibt, dass sein Wert eine bestimmte, von TMyBaseForm geerbte Klasse sein wird.
Hier ist eine mögliche Implementierung davon:
Funktion GetClassCount: integer;
beginnen
result := 3; // Zeigt an, dass 3 Klassen in dieser Dll exportiert werden
Ende;
Funktion GetClassTypeByIndex(const iIndex: integer;
var ClassType: MyBaseFormClass): WordBool;
beginnen
Ergebnis := True;
Fall iIndex von
0: ClassType := TFrmTest1;
1: ClassType := TFrmTest2;
2: ClassType := TFrmTest3;
anders
Ergebnis := Falsch;
Ende;
Ende;
Natürlich sollten die Einheiten, in denen sich TFrmTest1, TFrmTest2 und TFrmTest3 befinden, in der Verwendungsliste der Einheit enthalten sein. Die Implementierung von TFrmTest1 kann wie folgt aussehen:
TFrmTest1 = Klasse(TMyBaseForm)
geschützt
Funktion GetTitle: PChar override;
Ende;
Funktion TFrmTest1.GetTitle: Pchar;
beginnen
result := 'Hallo von TFrmTest1';
Ende;
Vergessen Sie nicht, GetClassCount und GetClassByIndex zur Exportliste hinzuzufügen. Aktivieren Sie dann beim Erstellen des DLL-Projekts bitte die Option „Laufzeitpaket verwenden“ im Optionspaket „Projekt“. Auf die konkreten Gründe wird später eingegangen.
Zu diesem Zeitpunkt ist die Arbeit an Dll abgeschlossen.
Der dritte Schritt ist die Implementierung der Hauptprogramm-Treiber-Engine:
Dieser Schritt ist relativ einfach – er besteht lediglich aus dem dynamischen Laden der DLL, dem anschließenden Aufruf der GetClassCount-Funktion und dem anschließenden Aufruf von GetClassByIndex. Schlüsselcode:
Var AClass: TMyBaseClass;
AForm: TMyBaseForm;
I, iCount: integer;
blResult: Boolean;
beginnen
// Den Teil über das Laden der dynamischen Bibliothek weglassen, vorausgesetzt, dass FPGetClassProc auf die GetClassCount-Funktion zeigt und FPGetClassByIndexProc auf GetClassByIndex zeigt, dann:
iCount := FPGetClassProc;
für I := 0 bis iCount ?C 1 do
beginnen
AClass := FPGetClassByIndex(I, blResult);
wenn blResult dann
beginnen
AForm := AClass.Create(application);
AForm.Caption := AForm.GetTitle;
AForm.Show;
Ende;
Ende;
//…
Ende;
Beachten Sie, dass Sie, ähnlich wie bei Dll, beim Erstellen der Ausgabedatei auch die Verwendung des Laufzeitpakets auswählen müssen. Dies liegt daran, dass die Nichtverwendung des Laufzeitpakets dazu führt, dass sich mehrere Kopien derselben Klasse im Speicher befinden. Wenn Sie also den Is-Operator darauf verwenden, wird „False“ zurückgegeben.
Musicwind®@HangZhou.Zhejiang.China
01.11.2001
Weitere Artikel
[ Ende des Artikels]