I got code like this
name := 'Foo';
If name = 'Foo' then
result := TFoo.Create
else if name = 'Bar' then
result := TBar.Create
else if name = 'FooFoo' then
result := TFooFoo.Create;
Is there a way just to do
result := $name.create
or some way of creating class based of a variable value?
All the classes extended the same base class.
The normal way to do this is with virtual constructors. A good example is
TComponent
which you are no doubt familiar.TComponent
has the following constructor:The other key to this is
TComponentClass
which is declared asclass of TComponent
.When the VCL streams .dfm files it reads the name of the class from the .dfm file and, by some process that we don't need to cover here, converts that name into a variable,
ComponentClass
say of typeTComponentClass
. It can then instantiate the object with:This is the big advantage of having a virtual constructor and I would encourage you to take the same approach.
If you have to use a string to identify the class then you'll still need to come up with a lookup routine to convert from the string class name to a class reference. You could, if convenient, hook into the same VCL mechanism that
TComponent
uses, namelyRegisterClass
.Alternatively if you could replace
name
in your code with a class reference then you could write:Starting with Delphi 2010, the enhanced RTTI allows you do this without having to creating your own Class Registry.
Using the
RTTI
Unit you have several options available.For Parameter Less Constructors one of the easiest is.
Here is an example of passing a parameter, using the
TRttiMethod.Invoke()
I wrote several articles on the
RTTI
unit as there is many options available.Updated Based on David Request:
Comparing the usage of construction using the Class Type (Virtual Constructor) with the
TRttiType.Invoke
Class Type Method: (Virtual Constructor)
TRttiType.Invoke() method
I personally find each serves a different purpose. If I know all the types up front the I use the Class Type Method.
You can use the
GetClass
function, but before you must register the classes using theRegisterClass
orRegisterClasses
methods.