Übergeben Sie Generic Record in einem Array von const

8

Ist es in irgendeiner Weise möglich, einen generischen Datensatz in einem Array von const-Argument an einen Funktionsaufruf zu übergeben?

Ich würde gerne den NULL-Bericht von Allen Bauer in einer Art von hausgemachtem Material verwenden ORM mit "Plain Old Delphi Objects" zum Zuordnen von Datenbankzeilen:

%Vor%

Der obige Code führt zu einem Fehler: "E2250: Keine überarbeitete Version der Funktion" Execute "kann mit diesen Argumenten aufgerufen werden" (übersetzt aus dem Französischen: E2250 Version von Version von 'Execute' ne peut être appelée aveces arguments )

Ich könnte FOptionalField explizit in String oder irgendetwas anderes umwandeln, da Nullable Ad-hoc-Operatoren außer Kraft setzt, aber ich muss wirklich wissen, ob die Nullable einen Wert hat oder nicht, bis ich das Array von const in das Feld Params des Datenbankabfrageobjekts mapped :

%Vor%

Hast du eine Idee, wie man diese Art von Konstrukt möglich macht? Ich finde einen Weg, indem ich eine explizite Umwandlung des Umwandlungsoperators zu Variant in Nullable mit RTTI hinzufüge, aber das ist ein bisschen schwierig, weil es eine explizite Umwandlung in Variant im Array von const call benötigt:

%Vor%     
ZeDalaye 10.05.2011, 08:48
quelle

2 Antworten

5

Wie Sie bereits festgestellt haben, ist record in den Parametern array of const im aktuellen Zustand des Compilers nicht erlaubt.

Tatsächlich haben TVarRec.VType -Werte keinen vtRecord.

Und der Variant -Typ selbst hat keinen varRecord -Typ, der von Delphi behandelt wird. Es gibt einen solchen Variantentyp in der Windows-Welt (zum Beispiel werden DotNet-Strukturen in vt_Record type in COM abgebildet), aber diese Art von Variante wird von Delphi nicht behandelt.

Es ist möglich, einen Zeiger auf die Typinfo des Datensatzes und dann auf den Datensatz zu übergeben:

%Vor%

Vielleicht eine nicht wundervolle Antwort, da Sie Generika verwenden ... aber zumindest einen Anfang ... In allen Fällen könnte ich das mit vorgenerischen Delphi-Compilern verwenden. Das TypeInfo () - Schlüsselwort war bereits sehr mächtig und schneller als die "neue" RTTI-Implementierung.

Eine andere Möglichkeit (kompatibel mit Generika) sollte sein, eine Datensatz-ID in den Datensatzinhalt einzufügen. Dann übergeben Sie den Datensatz als Zeiger, lesen Sie die ID und handeln Sie wie erwartet:

%Vor%

Dies könnte mit einer einfachen Erweiterung der ursprünglichen Nullable<T> -Definition erfolgen.

Post-Scriptum:

Das Verwenden von Datensätzen in einem ORM ist vielleicht nicht die beste Lösung ...

Das class -Modell ist in Delphi fortgeschrittener als das record/object -Modell, und da ein ORM sich um Objektmodellierung dreht, sollten Sie das beste verfügbare OOP-Modell, IMHO, verwenden. Wenn Sie sich auf Klassen statt auf Datensätze verlassen, können Sie Vererbung , eingebettete Typinformationen (über die Class -Methode oder nur über PPointer(aObject)^ ), Nullable-Werte und virtuelle Methoden (das ist sehr praktisch für ein ORM). Selbst das array of const -Parameters-Problem erlaubt die direkte Behandlung solcher vtObject -Typen und eine dedizierte virtuelle Klassenmethode. Ein ORM, das auf Datensätzen basiert, ist nur eine Möglichkeit, Tabellenzeilen zu serialisieren und Ihre Anwendung nicht mit OOP-Best Practices zu gestalten. Über die Leistung ist die Speicherzuweisung von class Instanzen kein Problem, verglichen mit potentiellen Problemen beim Kopieren von Datensätzen (die Funktion _CopyRecord RTL - die vom Compiler zB für Funktionsparameter versteckt aufgerufen wird - kann sehr langsam sein ).

In unserem ORM können wir beispielsweise dynamische Array-Eigenschaften handhaben, sogar dynamische Arrays von Datensätzen in Eigenschaften > (Delphi erzeugt keine RTTI für veröffentlichte Eigenschaften von Datensätzen, das ist ein anderes inkonsistentes Verhalten der aktuellen Klassenimplementierung). Wir serialisieren Datensätze und dynamische Arrays in JSON oder binär mit der "alten" RTTI, und es funktioniert sehr gut . Das Beste aus beiden Objektwelten zur Hand.

    
Arnaud Bouchez 10.05.2011, 09:39
quelle
1

Dank der Idee von Robert Love habe ich Implcit Cast zu TValue auf Nullable hinzugefügt und alle meine Params: array of const by const Params: array of TValue ersetzt.

Ich kann jetzt Params ohne Variant Casting bestehen:

%Vor%

Die MapParams-Methode wurde zu

%Vor%

Beachten Sie, dass ich die Typprüfung erzwang, indem ich die Datenbank zur Beschreibung und Erzwingung von Eingabeparametern aufforderte und die Art und Weise, in der Params aufgerufen wurden, änderte, so dass Exceptions ausgelöst werden, wenn Konvertierungen nicht möglich sind: Es gibt weitaus weniger Datentypen verfügbar in der Datenbank World als in der Delphi World.

    
ZeDalaye 10.05.2011 16:18
quelle

Tags und Links