Alexanders Lösung ist eine feine, aber in bestimmten Situationen nicht ausreichend. Angenommen, Sie möchten eine TClassFactory-Klasse einrichten, in der TClass-Referenzen zur Laufzeit und eine beliebige Anzahl später abgerufener Instanzen gespeichert werden können.
Eine solche Klassenfabrik würde niemals etwas über die tatsächlichen Typen der Klassen wissen, die sie enthält, und kann sie daher nicht in ihre entsprechenden Meta-Klassen einordnen. Um in solchen Fällen die richtigen Konstruktoren aufzurufen, funktioniert der folgende Ansatz.
Zuerst brauchen wir eine einfache Demo-Klasse (die öffentlichen Felder nicht stören, es ist nur zu Demonstrationszwecken).
interface
uses
RTTI;
type
THuman = class(TObject)
public
Name: string;
Age: Integer;
constructor Create(); virtual;
end;
implementation
constructor THuman.Create();
begin
Name:= 'John Doe';
Age:= -1;
end;
Jetzt instanziieren wir ein Objekt vom Typ THuman rein per RTTI und mit dem korrekten Konstruktoraufruf.
procedure CreateInstance();
var
someclass: TClass;
c: TRttiContext;
t: TRttiType;
v: TValue;
human1, human2, human3: THuman;
begin
someclass:= THuman;
// Invoke RTTI
c:= TRttiContext.Create;
t:= c.GetType(someclass);
// Variant 1a - instantiates a THuman object but calls constructor of TObject
human1:= t.AsInstance.MetaclassType.Create;
// Variant 1b - same result as 1a
human2:= THuman(someclass.Create);
// Variant 2 - works fine
v:= t.GetMethod('Create').Invoke(t.AsInstance.MetaclassType,[]);
human3:= THuman(v.AsObject);
// free RttiContext record (see text below) and the rest
c.Free;
human1.Destroy;
human2.Destroy;
human3.Destroy;
end;
Sie werden feststellen, dass die Objekte „human1“ und „human2“ auf Null initialisiert worden ist, das heißt, Name = ‚‘ und Alter = 0, was nicht das, was wir wollen. Das Objekt human3 enthält stattdessen die im Konstruktor von THuman angegebenen Standardwerte.
Beachten Sie jedoch, dass diese Methode erfordert, dass Ihre Klassen Konstruktormethoden mit nicht-Parametern haben. All das oben Gesagte wurde nicht von mir erdacht, sondern brillant und viel ausführlicher erläutert (z. B. der c.Freie Teil) in Rob Love's Tech Corner.
Ok, wenn ich das richtig verstehe, heißt das, wenn ich eine generische Objektfactory mit Delphi erstellen will, muss ich "class of TMyClass" einer Variablen zuweisen - aber das scheint nicht möglich. – mjn
Wenn Sie ein Objekt eines bestimmten Typs erstellen möchten, benötigen Sie Informationen zum Klassentyp. Wenn Sie keine Klasseninformationen haben, können Sie kein Objekt dieses Typs erstellen. Ziemlich offensichtlich;) – Alex