Solved

Creating objects from a string?

Posted on 1998-03-01
14
196 Views
Last Modified: 2013-11-23
Can I create an object of a certain type, when the classtype is given to me as a string?

eg:

function CreateObject(Str: String): TObject;
begin
  Result:=ObjectFromStr.Create; // need to get the Class from the string....
end;
0
Comment
Question by:bcrotaz
  • 6
  • 6
  • 2
14 Comments
 
LVL 4

Expert Comment

by:itamar
ID: 1359925
Hi bcrotaz,

I think that would be a problem to the compiler to resolve smth like this in run-time.

If you have a limited universe of possible classes, the only thing I can sugest you is test the possibilities like this:

If Str = 'TLabel' Then
   Result := TLabel.Create(owner);
...

Note that in many cases you have to provide an owner and in others you don't.

Sorry if it's not the answer you were waiting for, but sometimes the right answer is: NO - you can't.

Regards,
Itamar
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1359926
Hi

Itamar is only half right.  If the object is inherited from TPersistentClass (i.e. all Delphi components), then you can create it from a string.

As with most things, there are a few complications...

The component has to be registered with Delphi.
Let us consider an example with TListBox.

If you use a TListBox on your form, then it is already registered with Delphi.
If not, you have to register it with "RegisterClass(TListBox)".

To create it, you would then execute the following:

procedure TForm1.MakeAComp(ACompClass: string);
var
  AClass: TComponentClass;
  AComp: TComponent;
begin
  AClass := TComponentClass(GetClass(ACompClass));
  if (Assigned(AClass)) then begin
    AComp := AClass.Create(Self);
    if (AComp is TWinControl) then begin
      TWinControl(AComp).Parent := Self;
      TWinControl(AComp).Left := 100;
      TWinControl(AComp).Width := 200;
      // Etc...
    end;
  end;
end;


To call this procedure, first register all the possible components that will be dynamically created:

RegisterClasses([TListBox, TButton, TLabel, TMyThing]);

Then you can create them as & when you want:
MakeAComp('TListBox');
MakeAComp('TMyThing');

Regards,
JB
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1359927
Jimbob - can you send an answer, so I can grade you?
That's exactly the answer I wanted.
I've used ReadComponent and WriteComponent which work along similar lines, ie registering the classes first.  I just wasn't sure if you could do this.
What happens if you register the classes more than once in one process?
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 5

Expert Comment

by:JimBob091197
ID: 1359928
Hi bcrotaz
If you want my answer, you must 1st reject itamar's.  Sorry itamar...  ;-)

It is OK to call RegisterClass more than once for a component.

Cheers,
JB
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1359929
Sorry - Jimbob was much better!
0
 
LVL 4

Expert Comment

by:itamar
ID: 1359930
Hi all,

No problem, I also learned something else from this question. Feel free to grade JimBob's answer.

Regards,
Itamar
0
 
LVL 5

Accepted Solution

by:
JimBob091197 earned 200 total points
ID: 1359931
Hi bcrotaz

This be the answer then...

Regards,
JB
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1359932
Thanks
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1359933
HELLPPPP!!!
It doesn't call the constructor of my object.
The object is descended directly from TPersistent.
I've used:

function TForm1.MakeEventObject(NameOfClass: string): TVisualEvent;
var
  TheClass: TPersistentClass;
begin
  Result:=nil;
  TheClass := GetClass(NameOfClass);
  if Assigned(TheClass) then
    Result := TVisualEvent(TheClass.Create);
end;

When I use:
Event:=TVisualEvent.Create;
it calls the TVisuaEvent constructor.

When I use:
Event:=MakeEventObject('TVisualEvent');
it doesn't call it!

Any ideas?

0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1359934
Just from looking quickly, your line in MakeEventObject may be the problem:
Result := TVisualEvent(TheClass.Create);

This is associating Create with TheClass.

Try shifting it around, e.g.
Result := TVisualEvent(TheClass).Create;

JB
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1359935
Nope....Still doesn't do it!
0
 
LVL 1

Author Comment

by:bcrotaz
ID: 1359936
Aha!

type
  TVisualEventClass = class of TVisualEvent;

...

Result:=TVisualEventClass(TheClass).Create;

This is wierd.  The VisualEvent constructor now gets called correctly, but so do descendant objects.  Now why did the constructor not get called before as a descendant of TPersistent?
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1359937
Strange...  If you like, you can e-mail me your TVisualEvent code with some sample code of what is going wrong...
JB
0
 
LVL 5

Expert Comment

by:JimBob091197
ID: 1359938
(My last comment was based on your 2nd-last comment.)

I think that the constructor is called based on the VMT (Virtual Method Table) that comes from the class being created.  Why it works for descendants of TVisualEvent and not TPersistent is odd....
0

Featured Post

Announcing the Most Valuable Experts of 2016

MVEs are more concerned with the satisfaction of those they help than with the considerable points they can earn. They are the types of people you feel privileged to call colleagues. Join us in honoring this amazing group of Experts.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This video shows how to use Hyena, from SystemTools Software, to bulk import 100 user accounts from an external text file. View in 1080p for best video quality.
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question