Solved

Creating objects from a string?

Posted on 1998-03-01
14
194 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
Courses: Start Training Online With Pros, Today

Brush up on the basics or master the advanced techniques required to earn essential industry certifications, with Courses. Enroll in a course and start learning today. Training topics range from Android App Dev to the Xen Virtualization Platform.

 
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

Title # Comments Views Activity
ddeman not working in activex 3 103
Delphi TcxGrid group footer summary 3 261
Create a path if not exists 7 76
how to update exe applicatio from internet ? 6 76
A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, just open a new email message. In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…

813 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

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now