Solved

Creating objects from a string?

Posted on 1998-03-01
14
191 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
 
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
Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

 
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

Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

Join & Write a Comment

The uses clause is one of those things that just tends to grow and grow. Most of the time this is in the main form, as it's from this form that all others are called. If you have a big application (including many forms), the uses clause in the in…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
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…
This video discusses moving either the default database or any database to a new volume.

708 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

13 Experts available now in Live!

Get 1:1 Help Now