Creating a form object from string name

M

MikeB

Hi, I'd appreciate some help, please. I'm writing a VS2005 VB project
for school and one of the requirements is that every screen should have
a "Help" button.

I could do it by writing a clumsy case statement like this:

sub showHelp(byval frm as String)
Select Case (frm)
Case "Form1"
dim help as new Form1
help.Show()
Case "Form2"
Dim help as new Form2
help.Show()
.... etc

I searched and found Activator. I think this will make for better code.

So I wrote:

Sub ShowHelp(ByVal strFrom As String)
Dim frmhelp = Activator.CreateInstance(Nothing, strFrom)
frmhelp.show()
End Sub


but now I'm getting a TypeLoadException that says:

Could not load type 'hlpForm1' from assembly 'TestHelp,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

The form I'm testing from is Form1 and I do have a form hlpForm1
defined. They are in the same Namespace and in the same assembly in the
same project.

I'm lost. Can someone please help and tell me what I'm doing wrong?
Thanks.
 
T

Tom Shelton

MikeB said:
Hi, I'd appreciate some help, please. I'm writing a VS2005 VB project
for school and one of the requirements is that every screen should have
a "Help" button.

I could do it by writing a clumsy case statement like this:

sub showHelp(byval frm as String)
Select Case (frm)
Case "Form1"
dim help as new Form1
help.Show()
Case "Form2"
Dim help as new Form2
help.Show()
... etc

I searched and found Activator. I think this will make for better code.

So I wrote:

Sub ShowHelp(ByVal strFrom As String)
Dim frmhelp = Activator.CreateInstance(Nothing, strFrom)
frmhelp.show()
End Sub


but now I'm getting a TypeLoadException that says:

Could not load type 'hlpForm1' from assembly 'TestHelp,
Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'.

The form I'm testing from is Form1 and I do have a form hlpForm1
defined. They are in the same Namespace and in the same assembly in the
same project.

I'm lost. Can someone please help and tell me what I'm doing wrong?
Thanks.

I use this kind of dynamic code all the time for creating user controls
for screens on wizards or such, I have also used it to implement
command objects for a server. It made extending the servers command
set much simpler - I simply inherited from an abstract base command
object, and then would override a single method. I never even had to
touch the server again - I simply passed the command string to a
factory class which returned a reference to the abstract class and used
activator to create the actual comman implementation object (the object
name was the same as the command). And your right, it can make better
code (if used properly).

Anyway, for your specific problem - I believe that you need to pass the
name of the object. I know your saying that you did - I passed
"hlpForm1", but the fact is that isn't really the name of your class.
Your class is really going to be something (based on the error message)
"TestHelp.hlpForm1". Since all of these are in the same assembly, I
would try to change your function like this:

Sub ShowHelp(ByVal strFrom As String)
Dim frmhelp As Form = DirectCast
(Activator.CreateInstance(Nothing, "TestHelp." & strFrom), Form) ' we
do have option strict on right?
frmhelp.show()
End Sub

Casting to form is fine because it will be your super class. Anyway,
try that and if it doesn't work, maybe you could post a little more of
your code.
 
S

Stephany Young

Right on the money Tom, and you're absolutely correct, one must supply the
fully qualified class name.

I've successfully used this technique and I've a couple of notes that might
be helpful.

I prefer to use the overloads of the Activator.CreateInstance method that
take a Type as the first parameter as those return Object's as opposed to
the other overloads which return ObjectHandle's. This means that one has to
call the Type.GetType method using the class name string to get it to work,
e.g.:

Dim _f As Form =
DirectCast(Activator.CreateInstance(Type.GetType("TestHelp." & strFrom),
Form)
_f.Show()

If the target class is in the same assembly and shares the same namespace as
the calling code then, (although they wern't designed for this purpose), the
System.IO.Path.GetFileNameWithoutExtension and
System.IO.Path.ChangeExtension methods can be leveraged to construct the
string for the target class name, e,g:

Dim _t as Type =
Type.GetType(Path.ChangeExtension(Path.GetFileNameWithoutExtension(Me.Name),
"GenericForm")
Dim _f As Form = DirectCast(Activator.CreateInstance(_t), Form)
_f.Show()

or

Dim _t as Type =
Type.GetType(Path.ChangeExtension(Path.GetFileNameWithoutExtension(Me.Name),
"GenericForm")
Dim _f As Form =
DirectCast(Activator.CreateInstance(Type.GetType(Path.ChangeExtension(Path.GetFileNameWithoutExtension(Me.Name),
"GenericForm")), Form)
_f.Show()

This is particular useful where the Namespace is multilevel e.g. if Me.Name
returns MyApp.MyX.MainForm then Path.GetFileNameWithoutExtension returns
everything before the last '.' and Path.ChangeExtension appends a '.'
followed by whatever is specified.
 
T

Tom Shelton

Stephany said:
Right on the money Tom, and you're absolutely correct, one must supply the
fully qualified class name.

I've successfully used this technique and I've a couple of notes that might
be helpful.

I prefer to use the overloads of the Activator.CreateInstance method that
take a Type as the first parameter as those return Object's as opposed to
the other overloads which return ObjectHandle's. This means that one has to
call the Type.GetType method using the class name string to get it to work,
e.g.:

Actually, using the type overload is the way I usally do it. I had
forgotten that the other returns an ObjectHandle.
 
M

MikeB

Thank you to all for your help. I used this to make it work:

Dim _f As Form =
DirectCast(Activator.CreateInstance(Type.GetType("TestHelp." &
strFrom),
Form)
_f.Show()

I think there was a ")" missing, but I figured it out. It works great.

However, that gave me an idea and I have now created a single form with
a picturebox and a rich text box. Into these controls I load two files,
each with the same name as the name of the form calling for help. That
works too. Since I already have to write all the help text and capture
the screen images, it seems simpler to forego the creation of the
multiple individual forms my original approach would entail. Comments?
 
S

Stephany Young

Now you're getting into the realm of 'how long is a piece of string?'.

There is no right or wrong answer and everybody will have their own (valid)
opinion on the subject.

I note in you original post that this is for a school assignment. My advice
to you is to address the requirements of the assignment of which you have
previously only alluded to one aspect (the help button).

If your teacher/tutor is worth his/her salt, part of the marking process
will be to gauge how you have gone about the 'problem solving' aspect and,
supplying someone else's opinion and/or solution and presenting it as your
work is not what it's all about.

That said, I will say that, in my opinion, you are on the right track with a
'reusable' concept.
 
M

MikeB

Ouch. I wasn't intending to represent someone else's opinion as my own,
I was merely asking a group of people I think are more experienced than
myself if my current plan is better program-wise than my original plan
that I presented and that I got help with. If I wanted to use other
people's work, a previous copy of this project is doing the rounds, I
could have just taken a loook at that to see how it was solved
previously. I'm trying to learn here.

As for the teacher, I lost more point on pixellated images and bad
grammar than on anything else and there is no feedback on the type of
code that I write. I figured most of it out from the lecture and
working through the book and using the Visual Studio Help.

The Activator. thing was just over my head, hence I asked for help.
Even if I did ask for help, the solution I have now come up with is not
based on any help I've been given, I was just asking if it was good. I
prefer it because while I have the working code for the activator., I
don't really understand how it does what it does. If my own solution
wasn't good, I'd have to spend even more time trying to dig in deep
enough to understand how it actually works. With my courseload, time is
very scarce. I work part-time and have a full 12 hours of coursework.


Stephany said:
Now you're getting into the realm of 'how long is a piece of string?'.

There is no right or wrong answer and everybody will have their own (valid)
opinion on the subject.

I note in you original post that this is for a school assignment. My advice
to you is to address the requirements of the assignment of which you have
previously only alluded to one aspect (the help button).

If your teacher/tutor is worth his/her salt, part of the marking process
will be to gauge how you have gone about the 'problem solving' aspect and,
supplying someone else's opinion and/or solution and presenting it as your
work is not what it's all about.

That said, I will say that, in my opinion, you are on the right track with a
'reusable' concept.
 
S

Stephany Young

If I understand you correctly and your tutor is putting more emphasis on the
quality of the 'help' content than how it is implemented, then all I can say
is that I would be asking for my money back.

I appreciate that uasge of the Activator is probably outside or more
advanced than the remit of your course. You will note also that my response
was to add to Tom's response, rather than addressing your original post.

My more recent post was is response to your supplementary question as to
whether it was better to use a single form or use a seperate form for each
help 'context'. My main point here was that if you polled 20 people on the
subject you would, most likely, get 20 different views, all of which are
valid. Again, you will note that I did say that, in my view, you were were
on the right track with reusability.

My other comments were meant to be a generalisation prompted by the number
of posts we see in here looking for the answers to homework assignments and
were not meant to be a criticism of you personally.
 
C

Cor Ligthert [MVP]

Stephany and Tom,

Where is the showed method be better than something as?

Private function MyDialogShow(TheText)
dim myDialogForm as new MyDialogFormBase
MyDialogForm.TheText = TheText
return MyDialogFormBase.ShowDialog
End function

Or if it is about real forms just use the SortedList, with the string in the
key and the object in the value.

Seriously curious

Cor


Stephany Young said:
If I understand you correctly and your tutor is putting more emphasis on
the quality of the 'help' content than how it is implemented, then all I
can say is that I would be asking for my money back.

I appreciate that uasge of the Activator is probably outside or more
advanced than the remit of your course. You will note also that my
response was to add to Tom's response, rather than addressing your
original post.

My more recent post was is response to your supplementary question as to
whether it was better to use a single form or use a seperate form for each
help 'context'. My main point here was that if you polled 20 people on the
subject you would, most likely, get 20 different views, all of which are
valid. Again, you will note that I did say that, in my view, you were were
on the right track with reusability.

My other comments were meant to be a generalisation prompted by the number
of posts we see in here looking for the answers to homework assignments
and were not meant to be a criticism of you personally.
 
T

Tom Shelton

Cor said:
Stephany and Tom,

Where is the showed method be better than something as?

Private function MyDialogShow(TheText)
dim myDialogForm as new MyDialogFormBase
MyDialogForm.TheText = TheText
return MyDialogFormBase.ShowDialog
End function

Or if it is about real forms just use the SortedList, with the string in the
key and the object in the value.

Seriously curious

Cor

Cor - I was simply responding to his particular problem with
Activator.CreateInstance. To be completely honest, in this particular
case that is not the route I would take in a real world app.
Essentially, all of these "forms" are the same form just displaying
different text. Creating a bunch of forms with the same basic
functionality seems a little bit like more work then necessary - and I
believe that is what Stephany was hinting at to the OP. And your
solution is more along the lines of what would be more correct.

Still, I think it is good to become familar with the idea of dyanmic
object creation and reflection.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top