Creating objects from a string?

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;
LVL 1
bcrotazAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

itamarCommented:
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
JimBob091197Commented:
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
bcrotazAuthor Commented:
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
Get expert help—faster!

Need expert help—fast? Use the Help Bell for personalized assistance getting answers to your important questions.

JimBob091197Commented:
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
bcrotazAuthor Commented:
Sorry - Jimbob was much better!
0
itamarCommented:
Hi all,

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

Regards,
Itamar
0
JimBob091197Commented:
Hi bcrotaz

This be the answer then...

Regards,
JB
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
bcrotazAuthor Commented:
Thanks
0
bcrotazAuthor Commented:
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
JimBob091197Commented:
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
bcrotazAuthor Commented:
Nope....Still doesn't do it!
0
bcrotazAuthor Commented:
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
JimBob091197Commented:
Strange...  If you like, you can e-mail me your TVisualEvent code with some sample code of what is going wrong...
JB
0
JimBob091197Commented:
(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
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Delphi

From novice to tech pro — start learning today.