![]() |
Dynamisches Record?
Hi DP'ler!
Hab mir vorgenommen eine eigen Komponente für typisierte Dateien zu erstellen, da ich diese oft benutze. Die funktioniert soweit auch ganz gut (Next,Prior,BoF,EoF,RecNo,RecordCount,Append,Edit, Delete). Allerdings brauch ich ja zum Ansprechen einer typisierten Datei das Format der selbigen in Form eines Record-Typen, also z.B:
Delphi-Quellcode:
Da ich nun aber eine allg. Komponente erstellen möchte habe ich mir folgendes überlegt: Die Felddefinitionen lege ich inner einer INI oder etwas ähnlichem ab. jetzt kommen wir zu meinem Problem: Gibts in Delphi etwas in der Richtung von dynamischen Records? Also das ich die Header-Datei einlese und dann erst die Deklaration folgen lasse?
type
TBlubb = record LfdNr : Integer; KdNr : Integer; Name : String[50]; Vorname : String[50]; end; var IO : file of TBlubb; Schönen Dank im Voraus, |
Re: Dynamisches Record?
Das Einzige, was mir so auf die Schnelle einfällt wäre, statt n record ne class zu nehmen und die deiner Komponente dann zu übergeben. Dann kannst du mit TypeCasts arbeiten. Keine Ahnung hab ich noch nie gemacht. Oder du nimmst n Pointer und dann auch weiter mit TypeCast. :gruebel:
Hm... Probiers einfach mal aus, oder wart, bis jemand postet der davon mehr versteht als ich. mfg Christian [edit] P.S.: Ich personlich würde ne Klasse bevorzugen. Die müllen dann das Formulau nicht so zu und du kannst die class/den Pointer dem Creator übergeben. Aber das ist Geschmacksache... [/edit] |
Re: Dynamisches Record?
Mit Records geht das nicht, da die Namen der Felder im Kompilar gar nicht mehr existieren. Du könntest aber z.B. eine HashMap verwenden, in der due über den Schlüssel der Daten an deine Werte rankommst.
|
Re: Dynamisches Record?
Wenn es mit etwas Umwegen gehen darf, wäre eine TList-Ableitung möglich.
Diese würde den ItemTypen bekommen und könnte damit sofort loslegen. (die Felder einer Klasse sind nichts weiter als ein Record ;) ) Hier erstmal das FileOfClass-Dingsbums...
Delphi-Quellcode:
Ist nicht schön.... aber was kann in Verbindung mit typisierten Dateien schon schön sein. :mrgreen:
unit uFileOfClass;
interface uses Classes, Contnrs; type TFileOfClass = class(TObjectList) private fItemType: TClass; protected procedure WriteItemToStream(const aItem: TObject; aStream: TStream); virtual; function ReadItemFromStream(aStream: TStream): TObject; virtual; public property ItemType: TClass read fItemType; procedure SaveToStream(aStream: TStream); virtual; procedure LoadFromStream(aStream: TStream); virtual; procedure SaveToFile(const aFileName: string); virtual; procedure LoadFromFile(const aFileName: string); virtual; constructor Create(aItemType: TClass; aOwnsObjects: Boolean = True); virtual; end; implementation uses SysUtils; { TFileOfClass } constructor TFileOfClass.Create(aItemType: TClass; aOwnsObjects: Boolean); begin inherited Create(aOwnsObjects); fItemType := aItemType; end; procedure TFileOfClass.LoadFromFile(const aFileName: string); var Stream : TStream; begin Stream := TFileStream.Create(aFileName, fmOpenRead); try LoadFromStream(Stream); finally Stream.Free(); end; end; procedure TFileOfClass.LoadFromStream(aStream: TStream); begin while aStream.Position < aStream.Size do Add(ReadItemFromStream(aStream)); end; function TFileOfClass.ReadItemFromStream(aStream: TStream): TObject; begin Result := ItemType.NewInstance(); aStream.Read(Pointer(Result)^, ItemType.InstanceSize - SizeOf(Pointer)); end; procedure TFileOfClass.SaveToFile(const aFileName: string); var Stream : TStream; begin Stream := TFileStream.Create(aFileName, fmCreate); try SaveToStream(Stream); finally Stream.Free(); end; end; procedure TFileOfClass.SaveToStream(aStream: TStream); var i : Integer; begin for i := 0 to Count - 1 do begin WriteItemToStream(Items[i], aStream); end; end; procedure TFileOfClass.WriteItemToStream(const aItem: TObject; aStream: TStream); begin aStream.Write(Pointer(aItem)^, ItemType.InstanceSize - SizeOf(Pointer)); end; end. Dein "record" sähe wohl so aus.
Delphi-Quellcode:
Reinschreiben könntest du es so:
type
TBlubbClass = class private fLfdNr: Integer; fKdNr: Integer; fName: myShortString; fVorname: myShortString; published property LfdNr: Integer read fLfdNr write fLfdNr; property KdNr: Integer read fKdNr write fKdNr; property Name: myShortString read fName write fName; property Vorname: myShortString read fVorname write fVorname; end;
Delphi-Quellcode:
Auslesen wäre so möglich:
var
myList : TFileOfClass; Blubb : TBlubbClass; begin myList := TFileOfClass.Create(TBlubbClass); try Blubb := TBlubbClass.Create(); Blubb.LfdNr := 1; Blubb.KdNr := 10; Blubb.Name := 'Schulz'; Blubb.Vorname := 'Hans'; myList.Add(Blubb); Blubb := TBlubbClass.Create(); Blubb.LfdNr := 2; Blubb.KdNr := 20; Blubb.Name := 'Müller'; Blubb.Vorname := 'Bert'; myList.Add(Blubb); myList.SaveToFile('Miep.txt'); finally myList.Free(); end; end;
Delphi-Quellcode:
Dumm ist nur, dass es eigentlich totaler Blödsinn ist. :mrgreen:
var
myList : TFileOfClass; i : Integer; begin myList := TFileOfClass.Create(TBlubbClass); try myList.LoadFromFile('Miep.txt'); for i := 0 to myList.Count - 1 do with TBlubbClass(myList[i]) do ListBox1.Items.Add(Name + ', ' + Vorname); finally myList.Free(); end; end; Ändere den "record" zu einer Ableitung von TCollectionItem und schon kannst du auch strings und alles andere benutzen. Anstatt der TFileOfClass würde die ![]() Bist du auf Kompatibilität zu ekligen typisierten Dateien angewiesen musst du wohl den Weg oben gehen (und hoffen, dass der Compiler die Felder nicht irgendwann intern verdreht). Bist du es nicht sehe ich keine Ausrede weiterhin typisierte Dateien zu nehmen. ;)
Delphi-Quellcode:
type
TBlubbClass = class(TCollectionItem) private fLfdNr: Integer; fKdNr: Integer; fName: string; fVorname: string; published property LfdNr: Integer read fLfdNr write fLfdNr; property KdNr: Integer read fKdNr write fKdNr; property Name: string read fName write fName; property Vorname: string read fVorname write fVorname; end; |
Re: Dynamisches Record?
Das is mal ne Menge Input! Danke erst mal! Werde mit das morgen mal in aller Ruhe zu Gemüte führen, vor allem auch die DPCollection.
Ich hab bisher typisierte Dateien als Ersatz für Datenbanken genommen. Vorteil ist halt, dass die Dinger unschlagbar schnell sind und auch keinerlei Lizenzen für irgendwelche Server voraussetzen. Nachteil war bisher der immer wiederkehrende Aufwand die im Prinzip gleichen Sachen nochmal zu Proggen. Deswegen die Idee mit der Komponenten und erst zur Laufzeit deklarierten records. Aber wenn die DPCollection das gleiche bietet, warum sollte ich dann das Rad neu erfinden, gelle? Aber eine Frage noch Robert_G: Was findest du an typisierten Dateien eklig(abgesehen von der Handhabung für den Programmierer)? Schönen Abend noch, |
Re: Dynamisches Record?
Zitat:
Der einzige Nachteil der DP Collection ist, dass ihr Vorgänger und der Itemtyp in Classes.pas deklariert ist. (mehr als beschissen, wenn man Klasssen in Packages auslagert :? ) Sie ist aber langsamer als ein file of murks. Schließlich kann sie nicht einfach Daten in eine primitive Struktur schieben. Sie wird alle published properties speichern. (bzw auch andere, wenn man ![]() |
Re: Dynamisches Record?
noch eins... Kann TFileOfClass eine typ. Datei einlesen, die du mit einem gleich strukturierten Record erzeugt hattest?
Das hatte ich einfach angenommen, aber nicht getestet. :oops: |
Re: Dynamisches Record?
Zitat:
|
Re: Dynamisches Record?
Zitat:
Aber 1.5 MB VCL.dcp mitzuliefern verkneife ich mir dann doch solange es nur 1 oder 2 Echsen sind. Die installiert werden. Bei mehr ist es IMHO sogar sinnvoll die VCL als package zu nehmen. ;) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 19: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