一般是做个类似的对应表,通过实际类创建; 调用同理function GetObjByClzName(const AClzName : string; AOwner : TObject = nil): TObject; begin if AClzName = 'TForm' then Result := TForm.Create(AOwner) else if AClzName = 'TForm1' then Result := TForm1.Create(AOwner) else Result := nil; end;
unit Unit1;interfaceuses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;type TBaseClass=class of TBase; TForm1 = class(TForm) T1: TButton; procedure FormCreate(Sender: TObject); procedure T1Click(Sender: TObject); private { Private declarations } procedure CreateObjectByName( const ObjectName : string); public { Public declarations } end; TBase = class(TPersistent) public procedure Load;virtual; end; TC1=class(TBase) public procedure Load;override; end; TC2=class(TBase) public procedure Load;override; end; var Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject); begin RegisterClass(TBase); RegisterClass(TC1); RegisterClass(TC2); end; { TC2 }procedure TC2.Load; begin inherited; ShowMessage('TC2.Load'); end;{ TBase }procedure TBase.Load; begin ShowMessage('TBase.Load'); end;{ TC1 }procedure TC1.Load; begin inherited; ShowMessage('TC1.Load'); end;procedure TForm1.CreateObjectByName( const ObjectName : string); var fc : TBaseClass; f : TBase; begin fc := TBaseClass(FindClass(ObjectName)); f := fc.Create(); f.Load;
end; procedure TForm1.T1Click(Sender: TObject); begin CreateObjectByName('TC2'); end;end.
TBase = class(TPersistent) private FValue: Variant; procedure SetValue(const Value: Variant); public constructor Create; procedure Load;virtual; property Value : Variant read FValue write SetValue; end; TC1=class(TBase) public constructor Create(const Value : integer); procedure Load;override; end; TC2=class(TBase) public constructor Create(const Value : string); procedure Load;override; end; 如果子类的构造函数重写, 该如何写 constructor TBase.Create; begin //禁止使用基础类创建 raise Exception.Create('Error Message'); end;constructor TC2.Create(const Value: string); begin FValue := Value; end;
begin
if AClzName = 'TForm' then
Result := TForm.Create(AOwner)
else
if AClzName = 'TForm1' then
Result := TForm1.Create(AOwner)
else
Result := nil;
end;
unit Unit1;interfaceuses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;type
TBaseClass=class of TBase;
TForm1 = class(TForm)
T1: TButton;
procedure FormCreate(Sender: TObject);
procedure T1Click(Sender: TObject);
private
{ Private declarations }
procedure CreateObjectByName( const ObjectName : string);
public
{ Public declarations }
end;
TBase = class(TPersistent)
public
procedure Load;virtual;
end; TC1=class(TBase)
public
procedure Load;override;
end; TC2=class(TBase)
public
procedure Load;override;
end;
var
Form1: TForm1;implementation{$R *.dfm}procedure TForm1.FormCreate(Sender: TObject);
begin
RegisterClass(TBase);
RegisterClass(TC1);
RegisterClass(TC2);
end;
{ TC2 }procedure TC2.Load;
begin
inherited;
ShowMessage('TC2.Load');
end;{ TBase }procedure TBase.Load;
begin
ShowMessage('TBase.Load');
end;{ TC1 }procedure TC1.Load;
begin
inherited;
ShowMessage('TC1.Load');
end;procedure TForm1.CreateObjectByName(
const ObjectName : string);
var
fc : TBaseClass;
f : TBase;
begin
fc := TBaseClass(FindClass(ObjectName));
f := fc.Create();
f.Load;
end;
procedure TForm1.T1Click(Sender: TObject);
begin
CreateObjectByName('TC2');
end;end.
private
FValue: Variant;
procedure SetValue(const Value: Variant);
public
constructor Create;
procedure Load;virtual;
property Value : Variant read FValue write SetValue;
end; TC1=class(TBase)
public
constructor Create(const Value : integer);
procedure Load;override;
end; TC2=class(TBase)
public
constructor Create(const Value : string);
procedure Load;override;
end;
如果子类的构造函数重写, 该如何写
constructor TBase.Create;
begin
//禁止使用基础类创建
raise Exception.Create('Error Message');
end;constructor TC2.Create(const Value: string);
begin
FValue := Value;
end;
1:一般RegisterClass是写在initialization中,而在finalization中写unRegisterClass。这样的好处是,注册类一般用于序列化,而序列化并不依赖于某个类的构造。再者,即便class list中不会出现重复,你将RegisterClass放在构造函数中,每次创建实例的时候都调用也很没必要的。放在init和final中的好处还在于,如果该单元被package引用,则在包的加载和卸载时,能够正确的注册和注销class,单元的重用相对简单和可靠。
2:FindClass的时候,一定要判定返回值是否为nil,如果只是照着这个示例的写法,一旦出现没有注册的class,程序包出来的错位会很诡异,难于调试。