In dem Artikel "Starke Delphi RTTI - Eine Diskussion über die Notwendigkeit, mehrere Entwicklungssprachen zu verstehen", sagte ich, dass ich Delphis RTTI verwendet habe, um eine einfache Objektivierung von Datensätzen zu implementieren. In diesem Artikel wird meine Implementierungsmethode im Detail vorgestellt.
Beginnen wir mit einem einfachen Beispiel: Angenommen, es gibt eine Adodataset -Steuerung, die eine Verbindung zur Roswen -Datenbank herstellt, und SQL lautet:
Wählen Sie * vom Mitarbeiter aus
Jetzt müssen Sie die vier Fields EmployeeID, FirstName, LastName und Birthdate in seinen Inhalten in der ListView anzeigen. Der traditionelle Code ist wie folgt:
Mit adodataset1 beginnen, während nicht eof mit ListView1.Add beginnt. FieldbyName ('LastName') .Assstring);Hier gibt es mehrere Hauptprobleme:
1. Erstens gibt es viele Codes, die sehr ausführlich sind. Zum Beispiel, FieldbyName und Asxxx usw., insbesondere Asxxx, müssen Sie sich immer daran erinnern, welche Art von Feld sich auf jeden Fall leicht fehlerhaft macht. Wenn einige inkompatible Typen nicht automatisch konvertiert werden können, werden erst die Laufzeit Fehler gefunden.
2. Sie müssen die aktuelle Datensatzbewegung in der Schleife selbst verarbeiten. Andernfalls wird eine tote Schleife auftreten, sobald Sie es vergessen haben.
3. Das Wichtigste ist, dass der Feldname durch den String -Parameter weitergegeben wird. FieldbyName, es wird wahrscheinlich dazu führen, dass das Problem nur dann auftritt, wenn es sich für den Kunden verzögert. Diese Art von falschen Feldnamen ist einfach zu passieren, insbesondere wenn das Programm mehrere Tabellen verwendet, ist es einfach, die Feldnamen verschiedener Tabellen zu verwirren.
In dieser Ära, die von OO regiert wurde, müssen wir bei der Begegnung mit Datensätzen immer noch häufig in die Details der oben genannten relationalen Datenbank fallen. Natürlich gibt es auch eine Möglichkeit, sie jetzt loszuwerden, dh O/R -Kartierung, aber O/R -Mapping unterscheidet In diesem Fall brauchen wir nur ein einfaches Dataset -Objektivierungsschema.
Inspiriert von Java und anderen dynamischen Sprachen dachte ich, Delphis leistungsstarke RTTI zu verwenden, um dieses einfache Datensatz -Objektivierungsschema zu implementieren. Im Folgenden ist der Dataset Objectified Application Code, der dieselben Funktionen wie herkömmlicher Code implementiert:
Typ TDSPELDEE SetVariant; (Emp. Emp.); Emp.Free;
Die Verwendung ist sehr einfach. Das Wichtigste ist, zunächst eine Proxy -Klasse zu definieren, die das veröffentlichte Attribut verwendet, um alle Felder, einschließlich ihrer Typen, zu definieren, und dann können Sie den Datensatz auf Objekt manipulieren. Diese Proxy -Klasse wird von tmdatasetproxy abgeleitet, das RTTI verwendet, um die Zuordnung von Attributvorgängen zu Feldvorgängen zu implementieren. Die Implementierungseinheiten dieser Klasse werden nachstehend ausführlich erläutert.
An der Oberfläche gibt es eine zusätzliche Proxy-Klasse, die den Datensatz definiert, der mehr Code zu haben scheint, aber dies ist eine einmalige Sache, insbesondere wenn das Programm die gleiche Struktur von Datensätzen mehrmals wiederverwenden muss, den Code, der Code wird gemacht. Darüber hinaus ist die Definition dieser Proxy -Klasse sehr einfach. Die verwendeten Attributzugriffsfunktionen getXxx/setxxx werden alle in der Basisklasse TMDatasetproxy implementiert.
Schauen wir uns nun die Schleife an, die dem ursprünglichen Code entspricht:
1. FieldbyName und Asxxx werden nicht benötigt, und sie sind zu Attributoperationen in Proxy -Klassen geworden. es. Wenn der falsche Typ verwendet wird, wird während der Zusammenstellung ein Fehler gemeldet.
2. Verwenden Sie eine Foreach, um die Rekordtraversal durchzuführen, und müssen Sie sich keine Sorgen mehr machen, die Teufelschleife zu vergessen, die durch den nächsten verursacht wurde.
3. Der größte Vorteil ist, dass der Feldname zu einer Eigenschaft wird, sodass Sie die Vorteile der Feldnamenüberprüfung zum Kompilierzeit genießen können.
Diskutieren Sie nun über Tmdatasetproxy. Der Code seiner Implementierung ist wie folgt:
(********************************************************* *******************************************************************Datum: 28-05 Jan. ************************************************ (ANIDEX: Integer): Kurzschluss; ; ; Virtual; : TDATASET); CLASSINFO)^. Propcount; (FPropList) Freemem (FPropList); TMPropList.getPropName (AIndex: Integer): Kurzschluss; ; Ende; Prozedur tmdatasetproxy.Beginedit; begin if (fdataset.state <> dSedit) und (fdataset.state <> dsinsert) fdataset.edit; Ende; Verfahren tmdatasetproxy.endy; .State = dsinsert) dann fdataset.post; Ende; Funktion tmdatasetproxy.getInteger (aIndex: Integer): Integer; : Integer): double; begin Ergebnis: = fdataset.fieldbyName (fPropList.propnames [aindex]) .asfloat; end; function tmdatasetproxy.getString (AIndex: Integer): String; beginend: = fdataset.fieldbyname (fPropList. aIndex]) .Assstring; Ende; Funktion tmdatasetproxy.getVariant (aIndex: Integer): Variante; Begine Ergebnis: = fdataset.fieldbyname (fproplist.propnames [aindex]) .Value; ); ]) .Asfloat: = avalue; Ende; Verfahren tmdatasetproxy.setString (AIndex: Integer; Avalue: String); AInDEX: Ganze; Beginnen Sie ende;
Die TMPropList -Klasse ist eine Verkapselung einiger Funktionen der Attributoperation von RTTI. Seine Funktion besteht darin, einige von Delphi in der Typinfo -Einheit definierte RTTI -Funktionen zu verwenden, um eine von Tpersist abgeleitete Klasse zu implementieren, um die veröffentlichten Eigenschaftenlisteninformationen zu verwalten. Die Proxy -Klasse erhält den Attributnamen über diese Attributliste und arbeitet schließlich diesen Attributnamen und die entsprechenden Felder im Datensatz durch.
Tmdatasetproxy ist die Basisklasse der Datensatz -Proxy -Klasse. Der wichtigste Teil ist die Erstellung einer Eigenschaftsliste in der Nachverarbeitung.
Der Betrieb von Attributen implementiert nur vier Datentypen: Ganzzahl, Doppel/Float, String und Variante. Bei Bedarf können Sie Ihre eigene Proxy -Basisklasse auf dieser Grundlage abgeben, um die Implementierung anderer Datentypen zu implementieren. Die Implementierung des Austauschs davon. Für Typen, die nicht sehr häufig verwendet werden, wird empfohlen, die tatsächliche Proxy -Klasse vor der Implementierung zu definieren. Beispielsweise können Sie im vorherigen Beispiel angenommen, dass Tdatetime kein häufig verwendeter Typ ist, dies tun:
TDSPOWPOTION = CLASSE (TMDATASETPROXY) STECED -Funktion getDatetime (const Index: Integer): TDATETIME; Lesen Sie GetString SetString; (GetVariant (Index));
Auf diese Weise können Sie BirthDate direkt als tdatetime -Typ verwenden.
Darüber hinaus ist es möglich, einheitliche Vorgänge für einige benutzerdefinierte spezielle Datentypen bereitzustellen.
Außerdem wurde beginnedit vor allen setxxx gerufen, um zu vermeiden, dass Laufzeitfehler durch das Vergessen von Dataset.edit verursacht wurden.
Für die Wiederverwendung von Foreach wird nach Abschluss eines Durchlaufs auf den ersten Rekord für die nächste Schleife verschoben. Zusätzlich wird Endedit vor dem automatischen Einreichen der Änderungen aufgerufen.
Dieses Dataset -Objektivierungsschema ist eine sehr einfache Lösung. Dies liegt daran, dass Delphi immer noch eine native Entwicklungssprache ist. Keine Dynamik, sodass Sie nur die aktuelle Methode verwenden können, um sich zu registrieren.