2006. április 27., csütörtök

Construct a class instance from a string


Problem/Question/Abstract:

Is it possible to construct an instance of a class given the name of the class in a string variable? I would also want to test that the so named class actually exists and is a descendent of another known base class before construction.

Answer:

Yes, if some preconditions are met. The first thing you need is a class registry, a construct that allows you to register all the classes you want to create at run-time given the class name. The VCL already contains such a registry for TPersistent-derived classes (actually it is used only for TComponent-derived classes). Look at RegisterClass, GetClass and FindClass in the online help.

If you have your own hierachry of classes it is quite easy to set up your own class registry, using the TClassList class from the Contnrs unit (see online help). You would have one instance (a singleton) of TClasslist as your registry, to which you add your classes at run-time, typically from the Initialization section of the unit that implements the class in question.

Delphi has class reference types (see online help), which are types the values of which are classes. So you define such a type for your base class:

type
  TClassAClass = class of TClassA;

TClassA needs to have a virtual constructor (like Tcomponent) for this scheme to work properly. You can now derive other classes from TClassA, which may override the base classes constructor as appropiate. To find a class in the registry given its classname you iterate over the classlist:

function CreateInstance(const classname: string; minclass: TClassAClass): TClassA;
var
  i: Integer;
  classref: TClassAClass
begin
  Result := nil;
  for i := 0 to classlist.count - 1 do
  begin
    classref := TClassAClass(classlist[i]);
    if classref.ClassnameIs(classname) and classref.InheritsFrom(minclass) then
    begin
      Result := classref.Create;
      Break;
    end;
  end;
end;

If the constructor needs parameters you have to pass these to your CreateInstance function.

Nincsenek megjegyzések:

Megjegyzés küldése