![]() |
Delphi-Version: XE2
Typeinfo als Parameter
Hallo,
ich bin dabei ein altes Projekt von D5 auf XE2 zu portieren. In diesem Projekt wird sehr viel mit records gearbeitet. Diese enthalten Shortstrings (z.B. String[40]). Solche Records werden dann in Memory und/oder Filestreams abgelegt. Um von den Ansistrings wegzukommen probiere ich mehrere Möglichkeiten. Was funktioniert ist einmal ein neuer Datentyp z.B. TFixedstring.
Delphi-Quellcode:
Das bedeutet aber, dass für jede vorhandene Stringlänge ein eigener Datentyp
type
TFixString = record Value: array[0..41] of Char; class operator implicit(const aValue: string): TFixString; class operator implicit(const aValue: TFixString): string; end; declariert werden muss. String[22] -> Fixstring22 String[40] -> Fixstring40 String[128] -> Fixstring 128 ... Die 2. Möglichkeit ist die Ergänzung eines Record mit einer Methode write/readstream. Hier kann Variable und Dateninhalt über Rtti ausgelesen werden. Beispiel:
Delphi-Quellcode:
Beide Varianten bedingen, dass jeder record angepasst werden muss.
function TNodeData.ToString: String;
var AContext : TRttiContext; AField : TRttiField; ARecord : TRttiRecordType; AFldName : String; AValue : TValue; begin Result := ''; AContext := TRttiContext.Create; try ARecord := AContext.GetType(TypeInfo(TNodeData)).AsRecord; for AField in ARecord.GetFields do begin AFldName := AField.Name; AValue := AField.GetValue(@Self); Result := Result + AFldName + '|"' + EscapeQuotes(AValue.ToString) + '";'; end; finally AContext.Free; end; end; Was ich bauen möchte ist eigentlich eine Klasse z.B. TDatastream. Eine Methode TDatastream.Write(const rec) sollte den Record in einem Stream schreiben Jetzt suche ich eine Lösung um die Rtti Informationen von rec als typloser Parameter auszulesen. Hat wer da eine Idee? Gruß Peter |
AW: Typeinfo als Parameter
Zitat:
Und aus irgendwelchen Gründen wehren sich Alle gegen die Einführung von Makros, bzw. daß man Konstanten als "Parameter" in den Generics verwenden kann.
Delphi-Quellcode:
TFixString<Len> = record
Value: array[0..Len-1] of Char; class operator implicit(const aValue: string): TFixString; class operator implicit(const aValue: TFixString): string; end; Zitat:
Delphi-Quellcode:
kannst du problemlos als Parameter an deine Funktion übergen, oder hab ich dein Problem falsch verstanden?
P{Pointer} := TypeInfo(TNodeData);
Du könntest auch TReader und TWriter verwenden, so wie es z.B. die VCL mit den binären DFMs macht. Dort wurd zu jedem "Wert" auch der Typ mit gespeichert, was das Auslesen von "unbekannten" Datenstrukturen ermöglicht. Wenn man da Feldname+Wert abspeichet, dann kann man beim Auslesen die Daten sogar in einen anderen Record/Datenobjekt übertragen, da man den Feld-/Propertynamen kennt. - so kann man Speicher sparen, da man "unnötige" Daten weglässt (in der DFM stehen ja auch nur "abweichende" Property drin) - wenn man das ausgelesene Feld über seinen Namen sucht, passiert nichts, wenn man an der Struktur des Records was verändert (neue Felder irgendwo einfügen oder Alte entfernen) |
AW: Typeinfo als Parameter
Zitat:
Zitat:
Zitat:
Delphi-Quellcode:
und
TFixString<TMitPassenderLaenge: record> = record
Value: array[0..SizeOf(TMitPassenderLaenge)-1] of Char; // Achtung: SizeOf liefert gelegentlich 0 // oder Value: array[0..1] of TMitPassenderLaenge; // danach fleißig casten. :-( end;
Delphi-Quellcode:
oder
Str40 = string[40];
FixString40 = TFixString<Str40>;
Delphi-Quellcode:
Nicht elegant, aber besser als nix.
Arr40 = Array[0..39] of AnsiChar;
FixString40 = TFixString<Arr40>; |
AW: Typeinfo als Parameter
Sowas ginge auch, aber diese "brutalen" Castst machen keinen Spaß, vorallem Dank der massiven Bugs beim SizeOf. (dann lieber copy&paste)
Delphi-Quellcode:
TFixString<Arr> = record
Value: Arr; class operator implicit(const aValue: string): TFixString; class operator implicit(const aValue: TFixString): string; end; //Arr40 = array[0..39] of WideChar; //FixString40 = TFixString<Arr40>; FixString40 = TFixString<array[0..39] of WideChar>; |
AW: Typeinfo als Parameter
Zitat:
![]() |
AW: Typeinfo als Parameter
Zitat:
Vielleicht legst Du pro Record eine String-Property an, die diese AnsiStrings konvertiert, eventuell auch als lazy load (wenn Performance eine Rolle spielt). Ich habe das allerdings mal so gelöst, das meine 'Records' nun Klassen sind. Jede Klasse hat eine Load und Store Methode, die die einzelnen Daten/Felder bytegenau ausliest bzw. abspeichert, und zwar genauso, wie das der Record gemacht hat. Aus
Delphi-Quellcode:
wird dann
Bockread(myFile, @myRecord, SizeOf(myRecord))
Delphi-Quellcode:
. Das ist zwar ein wenig Arbeit, aber nur 1x und straight forward. Für die einzelnen Load/Store-Methoden schreibe ich Unit-Tests, um sicherzugehen, das die Daten genauso abgelegt/gelesen werden, wie der Record.
MyClass.Load(myFileStream);
Ich mach mir da keine großen Gedanken um Generics oder tolle allgemeingültige Lösungen. So ein
Delphi-Quellcode:
ist doch schwer zu lesen und bringt eigentlich auch nicht viel.
TFixString<irgendwas>
|
AW: Typeinfo als Parameter
Erst mal danke für die Tips.
Ich werde wohl Record gegen Class auswechseln müssen. Dadurch das records nicht erben können, gibt es keinen Vorfahr end eine typlose Übergabe funktioniert nicht richtig. Da die Record sequentiell in einem Memorystream gespeichert und ausgelesen werden, habe ich jetzt eine andere Lösung gefunden, die funktioniert. Ich habe mir eine Datenstreamklasse gebaut. Diese hat gleichnamige Methoden wie die TMemorystreamklasse. Es werden allerdings Klassreferenzern in einer TObjectliste verwaltet. Das funktioniert erst mal. Die Umsetzung von Ansi auf Unicode kann man in Delphi ja nicht gerade als gelungen bezeichnen. Abgesehen von unterschiedlichen Datentypen bei string und string[] , herrscht auch in der stringbibliothek ein ziemliches Wirrwar. Genauso gut könnte man Integer als 4 byt und Array of integer als jeweils 2 Byte implementieren. Ich hoffe ja das der Mobile Hype bei Embarcadero bald vorbei ist und es bei Delphi selbst wieder mal ein paar Fortschritte gibt. Gruß Peter |
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:37 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz