![]() |
Delphi-Version: 2010
Aus einem String eine Klasse erzeugen
Moin !
Ich teste gerade wieder ein bisschen mit RTTI und bin gerade zu der Frage gekommen ob man aus einem String eine Klasse erstellen kann. Bsp:
Delphi-Quellcode:
Das sei mal unsere Klasse.
type
TUserTest = class(TUser) private Test : Boolean; public end;
Delphi-Quellcode:
Geht das schon mit reinen Delphi Bordmitteln oder geht das nur mit RTTI?
var user : TUser
begin user := ??? 'TUserTest' ???.Create Hat da ggf. jemand ein Beispiel zu? |
AW: Aus einem String eine Klasse erzeugen
|
AW: Aus einem String eine Klasse erzeugen
Moin !
Das habe ich auch gefunden. Dort muss man aber die Klassen extra mittels RegisterClass(Txxxxx) registrieren. Geht das ggf. auch ohne? Man kann sich mit den RTTI Möglichkeiten von D2010 die Klassen auflisten lassen:
Delphi-Quellcode:
Evtl. kann man dann damit auch direkt eine Klasseninstanz erzeugen ?
var
aClass : TClass; context : TRttiContext; types : TArray<TRttiType>; aType : TRttiType; begin context := TRttiContext.Create; types := context.GetTypes; for aType in types do begin if aType.TypeKind = tkClass then begin aClass := aType.AsInstance.MetaclassType; Memo.Lines.Add(aClass.ClassName); end; end; |
AW: Aus einem String eine Klasse erzeugen
Du müßtest erstmal schauen ob/wie man mit der neuen RTTI "alle" Klassen auflistet, bzw. dort nach der Gewünschten sucht.
Wenn du dann Etwas ala TClass rausbekommst, dann könntest du darüber .Create aufrufen. Problem: Damit das richtige .Create aufgerufen wird, muß dieses als virtual deklariert sein, welches bei TObject (TClass = class of TObject) nicht der Fall ist.
Delphi-Quellcode:
Hier würde immer nur TObject.Create aufgerufen, egal ob zur (in C gespeicherten) Klasse ein anderes .Create deklariert wurde.
var C: TClass;
X := C.Create; Bei TComponent wäre dieses der Fall und wenn man seinen TComponent-Nachfolger registriert hat, dann geht es auch ohne RTTI (die VCL nutzt dieses ja ausgiebig, um die DFMs zu laden) OK, man könnte nun schauen, ob die RTTI hier auch noch eine Adresse für das richtige .Create liefert und Dieses direkt aufrufen. |
AW: Aus einem String eine Klasse erzeugen
Moin !
Also ich habe es jetzt mal so probiert und das funktioniert ... StrClass : TObject;
Delphi-Quellcode:
Das geht durch alle Klassen und wenn 'TUserTest' vorhanden ist, dann habe ich danach in StrClass eine Instanz.
var
aClass : TClass; context : TRttiContext; types : TArray<TRttiType>; aType : TRttiType; begin context := TRttiContext.Create; types := context.GetTypes; for aType in types do begin if aType.TypeKind = tkClass then begin aClass := aType.AsInstance.MetaclassType; if aClass.ClassName = 'TUserTest' then begin StrClass := aClass.NewInstance; TUserTest(StrClass).User := 'Test'; // Testzuweisung end; end; end; Sollte es so einfach gehen? :gruebel: |
AW: Aus einem String eine Klasse erzeugen
sieht so aus ...das funktioniert ebenfalls
Delphi-Quellcode:
procedure TForm1.Button2Click(Sender: TObject);
var aClass : TClass; context : TRttiContext; types : TArray<TRttiType>; aType : TRttiType; StrClass:TForm; begin context := TRttiContext.Create; types := context.GetTypes; for aType in types do begin if aType.TypeKind = tkClass then begin aClass := aType.AsInstance.MetaclassType; if aClass.ClassName = 'TForm2' then begin StrClass := TFormClass(aClass).Create(self); Tform(StrClass).Show; end; end; end; end; |
AW: Aus einem String eine Klasse erzeugen
Moin !
aber himitsu hat Recht mit dem Create. Meine urKlasse hat einen eigenen konstruktor:
Delphi-Quellcode:
Der wird nicht genutzt bei NewInstance.
constructor Create(name : string);
|
AW: Aus einem String eine Klasse erzeugen
Hiermit würde es ja gehen:
Delphi-Quellcode:
Aber da muss ich ja die Klasse dennoch als Cast mit angeben. :?
aType.GetMethod('Create').Invoke(aClass, ['']).AsObject as TUserTest
|
AW: Aus einem String eine Klasse erzeugen
vielleicht gibt es doch Fälle bei denen man es einsetzen möchte.
Für Controls funktioniert es wie gewünscht, für eigene Klassen könnte man gegf. Statt TClass syn. TObject beiliegnde TBaseObject verwenden. nur als Vorschlag.. btw. wenn die Klassen im Code nur deklariert sind und nirgends verwendet werden, läuft das ganze nicht da der Linker den Code wegoptimiert.
Delphi-Quellcode:
unit EXCreateByClassName;
// 20101125 Thomas Wassermann interface uses RTTI,TypInfo,Controls,Classes; type TBaseObject=Class Constructor Create(a:TValue);virtual; End; TBaseObjectClass= Class of TBaseObject; Function CreateClassByClassName(const s:String;a:Tvalue):TObject; Function CreateControlClassByClassName(const s:String;Owner:TComponent):TControl; implementation Function CreateClassByClassName(const s:String;a:Tvalue):TObject; var aClass : TClass; context : TRttiContext; types : TArray<TRttiType>; aType : TRttiType; begin Result := nil; context := TRttiContext.Create; types := context.GetTypes; for aType in types do begin if aType.TypeKind = tkClass then begin aClass := aType.AsInstance.MetaclassType; if aClass.ClassName = s then begin Result := TBaseObjectClass(aClass).Create(a); end; end; end; end; Function CreateControlClassByClassName(const s:String;Owner:TComponent):TControl; var aClass : TClass; context : TRttiContext; types : TArray<TRttiType>; aType : TRttiType; StrClass:TControl; begin Result := nil; context := TRttiContext.Create; types := context.GetTypes; for aType in types do begin if aType.TypeKind = tkClass then begin aClass := aType.AsInstance.MetaclassType; if aClass.ClassName = s then begin Result := TControlClass(aClass).Create(Owner); end; end; end; end; { TBaseObject } constructor TBaseObject.Create(a: TValue); begin inherited Create; end; end. |
AW: Aus einem String eine Klasse erzeugen
Zitat:
PS: NewInstanze ruft man überhaupt nicht auf, wenn man eine Klasse instantiieren will. NewInstanze reserviert nur den Speicher für die Klasse selber und richtet den eigenen Klassentypen ein und läd die Interface- und VirtualMethodes-Tabelle. Aber wenn in irgendwelchen Kontruktoren z.B. wichtige Dinge initialisiert werden (z.B. Unterobjekte erstellen und andere Dinge laden), dann fehlt dieses natürlich. (das wäre wie, wenn man statt Free/Destroy einfach nur FreeInstanze oder FreeMem aufruft) |
Alle Zeitangaben in WEZ +1. Es ist jetzt 06:51 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