I'd like to instantiate a class but I only have its name in a string. Is there a way?
This is from Delphi help (Delphi 2006, but also available from at least Delphi 7):
Syntax function GetClass(const AClassName: string): TPersistentClass;
Description Call GetClass to obtain a class from a class name. This class can be used as a parameter to routines that require a class. The Class must be registered before GetClass can find it. Form classes and component classes that are referenced in a form declaration (instance variables) are automatically registered when the form is loaded. Other classes can be registered by calling RegisterClass or RegisterClasses .
Here some sample code. Works as such only because TButton is a TControl and therefore the typecast is valid.
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TButton, TForm]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
CRef : TPersistentClass;
AControl : TControl;
begin
CRef := GetClass('TButton');
if CRef<>nil then
begin
AControl := TControl(TControlClass(CRef).Create(Self));
with AControl do
begin
Parent := Self;
Width := 50;
Height := 30;
end;
end;
end;
When I needed to do that, I Built my own Object Factory that uses a specially subclassed TStringList, I'm currently using Delphi 7 so the string list class supports only attach a Object to a String, then I got to subclass TStringList to make it possible handle Class Types too, so now I can instantiate a object just passing it's class name to the factory. Works that way:
1st - Load a Singleton Object Factory;
2st - Register any object to the factory, could be in the initialization section of the unit;
The main Factory's methods could be: isClassRegistered, registerClass, instantiateClass(ClassName: STring): TObject;
This way I can instantiate any object, or use a previous instantiated object, or even, a subset of they.
I rather use a Enumerated type instead of a string to identify a Class.
Remarks: It's a very, very terse example, a completely functional code is more complex, but, belive me, not too much.
Hi,
please may you tell me please, what's wrong with this code? I reused the code above:
. . .
TTripple=class (TPersistent)
private
FFont:TFont;
public
constructor Create;
Destructor Destroy;override;
published
property Font:TFont read FFont write FFont;
end;
var Form1: TForm1;
implementation
{$R *.dfm}
constructor TTripple.Create;
begin
inherited;
FFont:=TFont.Create;
end;
destructor TTripple.Destroy;
begin
FFont.Free;
inherited;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClasses([TButton, TForm, TTripple]);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
CRef : TPersistentClass;
APer : TPersistent;
begin
CRef := GetClass('TTripple');
if CRef<>nil then
begin
APer := TPersistent(TPersistentClass(CRef).Create);
ShowMessage(APer.ClassName); // TTriple (correct)
if APer is TTripple then (APer as TTripple).Font.Color:=90;
/// Here I get error message, because TTriple was not created yet... ?!?!?!
end;
end;