AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Aus einem String eine Klasse erzeugen

Ein Thema von moelski · begonnen am 25. Nov 2010 · letzter Beitrag vom 25. Nov 2010
Antwort Antwort
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#1

Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 10:49
Delphi-Version: 2010
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:
type
  TUserTest = class(TUser)
  private
    Test : Boolean;
  public

  end;
Das sei mal unsere Klasse.

Delphi-Quellcode:
var user : TUser
begin
  user := ??? 'TUserTest' ???.Create
Geht das schon mit reinen Delphi Bordmitteln oder geht das nur mit RTTI?
Hat da ggf. jemand ein Beispiel zu?
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#2

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 10:52
http://delphi.about.com/library/weekly/aa080905a.htm
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#3

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 10:57
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:
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;
Evtl. kann man dann damit auch direkt eine Klasseninstanz erzeugen ?
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#4

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 11:21
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:
var C: TClass;
X := C.Create;
Hier würde immer nur TObject.Create aufgerufen, egal ob zur (in C gespeicherten) Klasse ein anderes .Create deklariert wurde.

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.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

Geändert von himitsu (25. Nov 2010 um 11:24 Uhr)
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#5

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 11:30
Moin !

Also ich habe es jetzt mal so probiert und das funktioniert ...

StrClass : TObject;

Delphi-Quellcode:
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 = 'TUserTestthen begin
        StrClass := aClass.NewInstance;
        TUserTest(StrClass).User := 'Test'; // Testzuweisung
      end;
    end;
  end;
Das geht durch alle Klassen und wenn 'TUserTest' vorhanden ist, dann habe ich danach in StrClass eine Instanz.

Sollte es so einfach gehen?
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#6

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 11:43
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 = 'TForm2then begin
        StrClass := TFormClass(aClass).Create(self);
        Tform(StrClass).Show;
      end;
    end;
  end;
end;
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#7

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 11:49
Moin !

aber himitsu hat Recht mit dem Create.

Meine urKlasse hat einen eigenen konstruktor:
constructor Create(name : string); Der wird nicht genutzt bei NewInstance.
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010
  Mit Zitat antworten Zitat
moelski

Registriert seit: 31. Jul 2004
1.110 Beiträge
 
Delphi 2010 Professional
 
#8

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 11:51
Hiermit würde es ja gehen:
 aType.GetMethod('Create').Invoke(aClass, ['']).AsObject as TUserTest Aber da muss ich ja die Klasse dennoch als Cast mit angeben.
Dominik Schmidt
Greetz Dominik

I love Delphi 2007/2010

Geändert von moelski (25. Nov 2010 um 12:12 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Bummi
Bummi

Registriert seit: 15. Jun 2010
Ort: Augsburg Bayern Süddeutschland
3.470 Beiträge
 
Delphi XE3 Enterprise
 
#9

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 12:42
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.
Thomas Wassermann H₂♂
Das Problem steckt meistens zwischen den Ohren
DRY DRY KISS
H₂ (wenn bei meinen Snipplets nichts anderes angegeben ist Lizenz: WTFPL)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
43.136 Beiträge
 
Delphi 12 Athens
 
#10

AW: Aus einem String eine Klasse erzeugen

  Alt 25. Nov 2010, 13:11
Der wird nicht genutzt bei NewInstance.
Bei NewInstanze wird überhaupt kein Constructor aufgerufen.


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)
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests
  Mit Zitat antworten Zitat
Antwort Antwort


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 01:09 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz