dnoelpp
asked on
How to dynamically invoke Create(Owner) on a component?
I have a frame TBaseFrame and two derived frames TDerivedFrameAlpha and TDerivedFrameBeta. In a form I put a TBaseFrame, but the TBaseFrame is abstract and will never be used. Only the derived frames. Because there will be a lot more derived frames than Alpha and Beta I want to use the Factory pattern to create derived frames. Like this:
function GetDerivedFrame(ClassName: String): TBaseFrame;
Now I have a detail question. Components need to be created with Create(Owner). Like this:
Button := TButton.Create(Self);
How to do this dynamically?
Like this:
// Globals.ClassMap is a TList with registered classes
Clazz := Globals.ClassMap.Get('TBut ton');
Button := Clazz.NewInstance();
But this only calls:
Button := TButton.Create();
function GetDerivedFrame(ClassName:
Now I have a detail question. Components need to be created with Create(Owner). Like this:
Button := TButton.Create(Self);
How to do this dynamically?
Like this:
// Globals.ClassMap is a TList with registered classes
Clazz := Globals.ClassMap.Get('TBut
Button := Clazz.NewInstance();
But this only calls:
Button := TButton.Create();
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
What do you mean? When you creating factory you should define one common "abstract", all other objects in factory should be objects of common class or its descendants....
What do you mean? When you creating factory you should define one common "abstract" class, all other objects in factory should be objects of common class or its descendants....
ASKER
Yes it SHOULD. But what, if you make a mistake and put erroneously an other TComponent into the TList? Code defensively and think about, what happens... :-)
ASKER
Er, an other TObject, I wanted to say!
ASKER
By the way, I tried your solution. But I get an Access Violation.
--------8<-----------8<--- ---------- -
procedure TClassMap.Add(Clazz: TClass);
begin
ClassList.AddObject(Clazz. ClassName( ), Pointer(Clazz));
end;
function TClassMap.Get(const Name: String): TClass;
var
Index: Integer;
begin
Index := ClassList.IndexOf(Name);
if Index < 0 then Result := nil
else Result := TClass(ClassList.Objects[I ndex]);
end;
function TClassMap.CreateComponent(
const Name: String; Owner: TComponent
): TComponent;
var
Clazz: TClass;
begin
Clazz := Get(Name);
if Clazz <> nil then begin
Result := TComponent(Clazz).Create(O wner);
end else begin
Result := nil;
end;
end;
--------8<-----------8<--- ---------- -
I replaced CreateComponent with following code. This works perfectly, but I don't have a Create(Owner) any more, and we are again at the beginning of my question.
--------8<-----------8<--- ---------- -
function TClassMap.CreateComponent(
const Name: String; Owner: TComponent
): TComponent;
var
Clazz: TClass;
begin
Clazz := Get(Name);
if Clazz <> nil then begin
Result := Clazz.Create() As TComponent;
end else begin
Result := nil;
end;
end;
--------8<-----------8<--- ---------- -
--------8<-----------8<---
procedure TClassMap.Add(Clazz: TClass);
begin
ClassList.AddObject(Clazz.
end;
function TClassMap.Get(const Name: String): TClass;
var
Index: Integer;
begin
Index := ClassList.IndexOf(Name);
if Index < 0 then Result := nil
else Result := TClass(ClassList.Objects[I
end;
function TClassMap.CreateComponent(
const Name: String; Owner: TComponent
): TComponent;
var
Clazz: TClass;
begin
Clazz := Get(Name);
if Clazz <> nil then begin
Result := TComponent(Clazz).Create(O
end else begin
Result := nil;
end;
end;
--------8<-----------8<---
I replaced CreateComponent with following code. This works perfectly, but I don't have a Create(Owner) any more, and we are again at the beginning of my question.
--------8<-----------8<---
function TClassMap.CreateComponent(
const Name: String; Owner: TComponent
): TComponent;
var
Clazz: TClass;
begin
Clazz := Get(Name);
if Clazz <> nil then begin
Result := Clazz.Create() As TComponent;
end else begin
Result := nil;
end;
end;
--------8<-----------8<---
ASKER
This question is still open, I up to 100 points!
ASKER
Your solution doesn't quite work... It gives AV, but since nobody else answered I honor your work...
ASKER
TAbstractComponentClass(FL