Dynamically Load Components From Packages at Run Time (cont'd)
Create Run-Time Components Now that we've registered the T42Edit component and we've loaded the package, how do we actually create an instance of T42Edit? The hardcoded typename "T42Edit" should not exist (let alone compile) inside the executable, or at least not within the scope of the Edit42 unit (which makes it the fully qualified Edit42.T42Edit typename).
Let's use the result of the FindClass to (indirectly) create an instance of the component itself:
var
Cls: TPersistentClass;
Obj: TComponent;
begin
try
Cls := FindClass('T42Edit');
except
Cls := nil;
end;
if Cls <><> nil then
Obj := TComponentClass(Cls).Create(Self);
And of course we need to destroy the component with a call to Obj.Free after we've used it.
Use Dynamically Created Run-Time Components
There are two ways to use a dynamically created component for which the classname isn't hard-coded (like the T42Edit). The easiest way is to assume, correctly in this case, that T42Edit is derived from TEdit and it adds only special behavior to the component, not new properties, methods, or events. So you're assuming no new behavior exists, only enhanced behavior (using override). That being the case, we can simply cast our Obj to a TEdit component and use it as if it were a TEdit component (although it's in fact implemented as T42Edit):
var
Cls: TPersistentClass;
Obj: TComponent;
begin
try
Cls := FindClass('T42Edit');
except
Cls := nil;
end;
if Cls <><> nil then
begin
Obj := TComponentClass(Cls).Create(Self);
(Obj AS TEdit)..Parent := Self;
(Obj AS TEdit).Left := 100;
(Obj AS TEdit).Top := 100;
As an alternative, you could define the Obj variable as type TEdit to begin with, although you then need to cast the result from TComponentClass(Cls).Create(Self) to the TEdit type as well:
var
Cls: TPersistentClass;
Obj: TEdit;
begin
try
Cls := FindClass('T42Edit');
except
Cls := nil;
end;
if Cls <> nil then
begin
Obj := TEdit(TComponentClass(Cls).Create(Self));
Obj.Parent := Self;
Obj.Left := 100;
Obj.Top := 100;
Now we can use Obj as if it were a real TEdit, although in fact it is a T42Edit with enhanced behavior (like being right-aligned for example).
How do I dynamically load packages and use their components at run-time?
Write Delphi packages, dynamically load them, and create dynamic component instances in a way that can be the basis for a dynamic application plug-in architecture.
Find Out More
The T42Edit and T42Label components are implemented on Bob Swart's Web site in the Tip-of-the-Hat section.
What are your experiences with component use at Run-Time? Do you have a better way to build dynamic application plug-in architectures. Let us know in the database development discussion groups!