473,326 Members | 2,175 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,326 software developers and data experts.

Best way to instantiate a class when the class name is passed as variable?

I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.

Right now I have

Sub RunReports(sReport)
Select Case sReport
Case "CRByDistrict"
oReport = New CRByDistrict

Case "CRCareConversionRate"
oReport = New CRCareConversionRate

Case (etc.....)
End Select

oReport.Build ' All classes implement a Build method
End Sub

For example, if the scheduler says it's time to run the "CRByDistrict"
report I want to pass in "CRByDistrict" and invoke

oReport = New <className> ' One line handles all reports

where in this case <className> is "CRByDistrict". I've looked at
Activator.CreateInstance and some other things, but I can't figure out
the best, simplest way to do this.

I'm tired of maintaining what has become a huge Select Case statement
each time I add a new report (class).

Thanks,
Brian
Nov 21 '05 #1
13 2272
IMHO, Activactor.CreateInstance should be the way to go for you. Since you
have all your classes in the same project (and hence the same assembly), it
should be pretty simple to use this method. Something like:

dim reportType = Type.GetType(sReport)
dim reportObject = Activator.CreateInstance(reportType)

Or

dim reportObject = Activator.CreateInstance(Nothing, sReport)

hope that helps..
Imran.

"Brian" <br******@hotmail.com> wrote in message
news:b6**************************@posting.google.c om...
I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.

Right now I have

Sub RunReports(sReport)
Select Case sReport
Case "CRByDistrict"
oReport = New CRByDistrict

Case "CRCareConversionRate"
oReport = New CRCareConversionRate

Case (etc.....)
End Select

oReport.Build ' All classes implement a Build method
End Sub

For example, if the scheduler says it's time to run the "CRByDistrict"
report I want to pass in "CRByDistrict" and invoke

oReport = New <className> ' One line handles all reports

where in this case <className> is "CRByDistrict". I've looked at
Activator.CreateInstance and some other things, but I can't figure out
the best, simplest way to do this.

I'm tired of maintaining what has become a huge Select Case statement
each time I add a new report (class).

Thanks,
Brian

Nov 21 '05 #2
In article <b6**************************@posting.google.com >, Brian wrote:
I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.

Right now I have

Sub RunReports(sReport)
Select Case sReport
Case "CRByDistrict"
oReport = New CRByDistrict

Case "CRCareConversionRate"
oReport = New CRCareConversionRate

Case (etc.....)
End Select

oReport.Build ' All classes implement a Build method
End Sub

For example, if the scheduler says it's time to run the "CRByDistrict"
report I want to pass in "CRByDistrict" and invoke

oReport = New <className> ' One line handles all reports

where in this case <className> is "CRByDistrict". I've looked at
Activator.CreateInstance and some other things, but I can't figure out
the best, simplest way to do this.

I'm tired of maintaining what has become a huge Select Case statement
each time I add a new report (class).

Thanks,
Brian


I am assuming that all of the report classes implement a specific
interface or inherit from a common base class - but for this example
I'll assume an interface named IReport that has the Build method defined.
Given the above, something like this should work:

Private Sub RunReport (ByVal ReportType As String)
Dim report As IReport = DirectCast _
(Activator.CreateInstance (Type.GetType (ReportType)), _
IReport)

report.Build()

End Sub

--
Tom Shelton [MVP]
Nov 21 '05 #3
oops..that wouldn't even compile ;-)

I meant:

dim reportType As Type = Type.GetType(sReport)
dim reportObject As Object = Activator.CreateInstance(reportType)

Or

dim reportObject as Object = Activator.CreateInstance(Nothing, sReport)

"Imran Koradia" <no****@microsoft.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
IMHO, Activactor.CreateInstance should be the way to go for you. Since you
have all your classes in the same project (and hence the same assembly), it should be pretty simple to use this method. Something like:

dim reportType = Type.GetType(sReport)
dim reportObject = Activator.CreateInstance(reportType)

Or

dim reportObject = Activator.CreateInstance(Nothing, sReport)

hope that helps..
Imran.

"Brian" <br******@hotmail.com> wrote in message
news:b6**************************@posting.google.c om...
I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.

Right now I have

Sub RunReports(sReport)
Select Case sReport
Case "CRByDistrict"
oReport = New CRByDistrict

Case "CRCareConversionRate"
oReport = New CRCareConversionRate

Case (etc.....)
End Select

oReport.Build ' All classes implement a Build method
End Sub

For example, if the scheduler says it's time to run the "CRByDistrict"
report I want to pass in "CRByDistrict" and invoke

oReport = New <className> ' One line handles all reports

where in this case <className> is "CRByDistrict". I've looked at
Activator.CreateInstance and some other things, but I can't figure out
the best, simplest way to do this.

I'm tired of maintaining what has become a huge Select Case statement
each time I add a new report (class).

Thanks,
Brian


Nov 21 '05 #4
I guess I'm missing something fundamental here. I tried your (very helpful)
suggestion, but Type.GetType(sReport) returns Nothing in my case.

Should I be doing something in my class definitions to set their Type? I
don't have a base class.

Thanks,
Brian

"Imran Koradia" <no****@microsoft.com> wrote in message
news:%2***************@TK2MSFTNGP15.phx.gbl...
oops..that wouldn't even compile ;-)

I meant:

dim reportType As Type = Type.GetType(sReport)
dim reportObject As Object = Activator.CreateInstance(reportType)

Or

dim reportObject as Object = Activator.CreateInstance(Nothing, sReport)

"Imran Koradia" <no****@microsoft.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
IMHO, Activactor.CreateInstance should be the way to go for you. Since you have all your classes in the same project (and hence the same assembly),

it
should be pretty simple to use this method. Something like:

dim reportType = Type.GetType(sReport)
dim reportObject = Activator.CreateInstance(reportType)

Or

dim reportObject = Activator.CreateInstance(Nothing, sReport)

hope that helps..
Imran.

"Brian" <br******@hotmail.com> wrote in message
news:b6**************************@posting.google.c om...
I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.

Right now I have

Sub RunReports(sReport)
Select Case sReport
Case "CRByDistrict"
oReport = New CRByDistrict

Case "CRCareConversionRate"
oReport = New CRCareConversionRate

Case (etc.....)
End Select

oReport.Build ' All classes implement a Build method
End Sub

For example, if the scheduler says it's time to run the "CRByDistrict"
report I want to pass in "CRByDistrict" and invoke

oReport = New <className> ' One line handles all reports

where in this case <className> is "CRByDistrict". I've looked at
Activator.CreateInstance and some other things, but I can't figure out
the best, simplest way to do this.

I'm tired of maintaining what has become a huge Select Case statement
each time I add a new report (class).

Thanks,
Brian



Nov 21 '05 #5
Sorry - I should have been more complete. If your class is under a
namespace, you'll need to provide the namespace information to the GetType
method as well. By default, VB .NET uses the application name as the default
namespace which is why you would need to do this. You can check the default
namespace from Project --> <your project> Properties -- > Root Namespace
field. You can change that to whatever you like or you can even wipe it out
altogether. In general, you'll need to provide the entire namespace
hierarchy. For example:

If your project name is "myProject", by default, your root namespace will be
"myProject". (For project names with spaces, I believe VB .NET uses and
underscore instead of the spaces; so "My Project" becomes "My_Project").
Suppose your report class is something like:

NameSpace AllReports
....
....
Class CRByDistrict
Public Sub Build( )

End Sub
End Class

Class CRCareConversionRate
Public Sub Build( )

End Sub
End Class
....
....
End NameSpace

Then you would do:

Sub RunReports(sReport)
Dim reportType As Type = _
Type.GetType("myProject." & "AllReports." & sReport)
Dim reportObject As Object = _
Activator.CreateInstance(myType)
reportType.InvokeMember("Build", _
Reflection.BindingFlags.InvokeMethod, _
Nothing, reportObject, Nothing)
End Sub

Ofcourse, if you have no namespaces and if you are going to wipe out the
default namespace as well, then you can directly use the report class name
in the Type.GetType method. Thats upto how you would want it.

hope that helps..
Imran.
"Brian Fenske" <br******@hotmail.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
I guess I'm missing something fundamental here. I tried your (very
helpful)
suggestion, but Type.GetType(sReport) returns Nothing in my case.

Should I be doing something in my class definitions to set their Type? I
don't have a base class.

Thanks,
Brian

"Imran Koradia" <no****@microsoft.com> wrote in message
news:%2***************@TK2MSFTNGP15.phx.gbl...
oops..that wouldn't even compile ;-)

I meant:

dim reportType As Type = Type.GetType(sReport)
dim reportObject As Object = Activator.CreateInstance(reportType)

Or

dim reportObject as Object = Activator.CreateInstance(Nothing, sReport)

"Imran Koradia" <no****@microsoft.com> wrote in message
news:%2****************@TK2MSFTNGP10.phx.gbl...
> IMHO, Activactor.CreateInstance should be the way to go for you. Since you > have all your classes in the same project (and hence the same
> assembly),

it
> should be pretty simple to use this method. Something like:
>
> dim reportType = Type.GetType(sReport)
> dim reportObject = Activator.CreateInstance(reportType)
>
> Or
>
> dim reportObject = Activator.CreateInstance(Nothing, sReport)
>
> hope that helps..
> Imran.
>
> "Brian" <br******@hotmail.com> wrote in message
> news:b6**************************@posting.google.c om...
> > I have many similar classes in a project, one for each type of report
> > my app can create. I want to instantiate them based on a value
> > passed
> > in by a scheduler module.
> >
> > Right now I have
> >
> > Sub RunReports(sReport)
> > Select Case sReport
> > Case "CRByDistrict"
> > oReport = New CRByDistrict
> >
> > Case "CRCareConversionRate"
> > oReport = New CRCareConversionRate
> >
> > Case (etc.....)
> > End Select
> >
> > oReport.Build ' All classes implement a Build method
> > End Sub
> >
> > For example, if the scheduler says it's time to run the
> > "CRByDistrict"
> > report I want to pass in "CRByDistrict" and invoke
> >
> > oReport = New <className> ' One line handles all reports
> >
> > where in this case <className> is "CRByDistrict". I've looked at
> > Activator.CreateInstance and some other things, but I can't figure
> > out
> > the best, simplest way to do this.
> >
> > I'm tired of maintaining what has become a huge Select Case statement
> > each time I add a new report (class).
> >
> > Thanks,
> > Brian
>
>



Nov 21 '05 #6
On 2004-09-14, Imran Koradia <no****@microsoft.com> wrote:
Sorry - I should have been more complete. If your class is under a
namespace, you'll need to provide the namespace information to the GetType
method as well.


It's worth adding that Type.GetType is more than a bit flaky. It works
well with the standard assemblies, usually works inside a single
assembly application, but once you get into multiple assemblies all bets
are off.

In all honesty, I've never figured out the pattern to when it works or
not. Sometimes it works even across assemblies, and sometimes it
doesn't (even using the AssemblyQualifiedName doesn't help in this
situation). I'd be very interested if somebody has spent the time to
track this down, since it's a very useful function.

Personally, I'd be very wary of using it in the situation in this
thread, since with this type of system the logical next step is a plugin
system where you load new report types without recompiling, and
Type.GetType is highly unlikely to work reliably in that situation.
You're probably better off looping through known assemblies looking for
a specific interface (do it once at startup then stash away the types
you find). It's a bit more code right now, but you gain a lot in
robustness and expandability.

Nov 21 '05 #7
Hmm. I haven't had problems with the GetType method as such but honestly,
I've not used it so extensively either to be a good judge of its
reliability. Brian - if you think thats going to be a problem, here's
another way to accomplish the same thing:

Imports System.Reflection

Dim reportObject As Object = _
[Assembly].GetExecutingAssembly.CreateInstance("myProject" & sReport)
CallByName(reportObject, "Build", CallType.Method, Nothing)

Imran.

"David" <df*****@woofix.local.dom> wrote in message
news:slrnckck1a.qmv.df*****@woofix.local.dom...
On 2004-09-14, Imran Koradia <no****@microsoft.com> wrote:
Sorry - I should have been more complete. If your class is under a
namespace, you'll need to provide the namespace information to the
GetType
method as well.


It's worth adding that Type.GetType is more than a bit flaky. It works
well with the standard assemblies, usually works inside a single
assembly application, but once you get into multiple assemblies all bets
are off.

In all honesty, I've never figured out the pattern to when it works or
not. Sometimes it works even across assemblies, and sometimes it
doesn't (even using the AssemblyQualifiedName doesn't help in this
situation). I'd be very interested if somebody has spent the time to
track this down, since it's a very useful function.

Personally, I'd be very wary of using it in the situation in this
thread, since with this type of system the logical next step is a plugin
system where you load new report types without recompiling, and
Type.GetType is highly unlikely to work reliably in that situation.
You're probably better off looping through known assemblies looking for
a specific interface (do it once at startup then stash away the types
you find). It's a bit more code right now, but you gain a lot in
robustness and expandability.

Nov 21 '05 #8
* br******@hotmail.com (Brian) scripsit:
I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.


\\\
Dim frm As Form = _
DirectCast( _
Activator.CreateInstance( _
Type.GetType("MyApplication.SampleForm") _
), _
Form _
)
frm.Show()
///

More general:

\\\
Private Function CreateClassByName( _
ByVal PartialAssemblyName As String, _
ByVal QualifiedClassName As String _
) As Object
Return _
Activator.CreateInstance( _
[Assembly].LoadWithPartialName( _
PartialAssemblyName _
).GetType(QualifiedClassName) _
)
End Function
///

Usage:

\\\
Dim c As Control = _
DirectCast( _
CreateClassByName( _
"System.Windows.Forms", _
"System.Windows.Forms.Button" _
), _
Control _
)
With c
.Location = New Point(10, 10)
.Size = New Size(80, 26)
.Text = "Hello World"
End With
Me.Controls.Add(c)
///

--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>
Nov 21 '05 #9
In article <sl********************@woofix.local.dom>, David wrote:
On 2004-09-14, Imran Koradia <no****@microsoft.com> wrote:
Sorry - I should have been more complete. If your class is under a
namespace, you'll need to provide the namespace information to the GetType
method as well.


It's worth adding that Type.GetType is more than a bit flaky. It works
well with the standard assemblies, usually works inside a single
assembly application, but once you get into multiple assemblies all bets
are off.


Never had a lick of trouble with it myself....

--
Tom Shelton [MVP]
Nov 21 '05 #10
Well, after trying many different ways to get back a Type, I gave up on
GetType.

I used Object Browser to note that my Namespace is indeed the name of my
project as well as the executable (which must be the defaults for a VB
project since I didn't attempt to change any of them when I ran the project
wizard): CRMReportGenerator

So I tried the following, all of which return Nothing:

Type.GetType(sReport)
Type.GetType("CRMReportGenerator." & sReport)
Type.GetType("CRMReportGenerator.CRMReportGenerato r." & sReport)
Type.GetType("DSR Report Generator.CRMReportGenerator." & sReport) ' Here I
tried the Assembly name found in Assembly.vb

Maybe there is a combo I didn't try that works.

Anyway, here is what did work:

Imports System.Reflection

Dim oReport as Object
oReport =
[Assembly].GetExecutingAssembly.CreateInstance("CRMReportGen erator." &
sReport)
oReport.Build

Short and sweet.

Thank you all for your help!

Brian

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:e6**************@tk2msftngp13.phx.gbl...
* br******@hotmail.com (Brian) scripsit:
I have many similar classes in a project, one for each type of report
my app can create. I want to instantiate them based on a value passed
in by a scheduler module.


\\\
Dim frm As Form = _
DirectCast( _
Activator.CreateInstance( _
Type.GetType("MyApplication.SampleForm") _
), _
Form _
)
frm.Show()
///

More general:

\\\
Private Function CreateClassByName( _
ByVal PartialAssemblyName As String, _
ByVal QualifiedClassName As String _
) As Object
Return _
Activator.CreateInstance( _
[Assembly].LoadWithPartialName( _
PartialAssemblyName _
).GetType(QualifiedClassName) _
)
End Function
///

Usage:

\\\
Dim c As Control = _
DirectCast( _
CreateClassByName( _
"System.Windows.Forms", _
"System.Windows.Forms.Button" _
), _
Control _
)
With c
.Location = New Point(10, 10)
.Size = New Size(80, 26)
.Text = "Hello World"
End With
Me.Controls.Add(c)
///

--
M S Herfried K. Wagner
M V P <URL:http://dotnet.mvps.org/>
V B <URL:http://dotnet.mvps.org/dotnet/faqs/>

Nov 21 '05 #11
Oops, I was not entirely correct. My Assembly Title is "DSR Report
Generator". My AssemblyName and Root Namespace are "CRMReportGenerator"

Brian
"Tom Shelton" <to*@YOUKNOWTHEDRILLmtogden.com> wrote in message
news:u%****************@tk2msftngp13.phx.gbl...
In article <sl********************@woofix.local.dom>, David wrote:
On 2004-09-14, Imran Koradia <no****@microsoft.com> wrote:
Sorry - I should have been more complete. If your class is under a
namespace, you'll need to provide the namespace information to the GetType method as well.


It's worth adding that Type.GetType is more than a bit flaky. It works
well with the standard assemblies, usually works inside a single
assembly application, but once you get into multiple assemblies all bets
are off.


Never had a lick of trouble with it myself....

--
Tom Shelton [MVP]

Nov 21 '05 #12
> Anyway, here is what did work:

Imports System.Reflection

Dim oReport as Object
oReport =
[Assembly].GetExecutingAssembly.CreateInstance("CRMReportGen erator." &
sReport)
That's what I suggested in my 3rd post...
oReport.Build


This will only work if you have Option Strict Off. If you have Option Strict
On, you would need to typecast to the actual report type. Since dynamic
casting cannot be accomplished, you'll need to use CallByName to execute the
method as I mentioned in that post.

Imran.
Nov 21 '05 #13
In article <uf**************@TK2MSFTNGP15.phx.gbl>, Imran Koradia wrote:
Anyway, here is what did work:

Imports System.Reflection

Dim oReport as Object
oReport =
[Assembly].GetExecutingAssembly.CreateInstance("CRMReportGen erator." &
sReport)


That's what I suggested in my 3rd post...
oReport.Build


This will only work if you have Option Strict Off. If you have Option Strict
On, you would need to typecast to the actual report type. Since dynamic
casting cannot be accomplished, you'll need to use CallByName to execute the
method as I mentioned in that post.

Imran.

Or just make them all implement a specific interface... That way, you
can have early binding....

Dim report As IReport
report = CType (....., IReport)
report.Build()
In fact, that is the way I would probably do this.
--
Tom Shelton [MVP]
Nov 21 '05 #14

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

35
by: Swartz | last post by:
Hi all. I'm working here on a small project of mine. I'm not new to programming, but I'm new to PHP. You have to understand that I'm coming from C++, OOP world, so my code might seems a little...
4
by: David | last post by:
Hello. I am looking for advice on what is "best practice" regarding looping through a form to check its checkboxes and associated data fields. Here is what I am trying to do (Here is the page...
4
by: Chuck Ritzke | last post by:
I keep asking myself this question as I write class modules. What's the best/smartest/most efficient way to send a large object back and forth to a class module? For example, say I have a data...
0
by: Anonieko Ramos | last post by:
ASP.NET Forms Authentication Best Practices Dr. Dobb's Journal February 2004 Protecting user information is critical By Douglas Reilly Douglas is the author of Designing Microsoft ASP.NET...
7
by: h7qvnk7q001 | last post by:
I'm trying to implement a simple server-side form validation (No Javascript). If the user submits a form with errors, I want to redisplay the same form with the errors highlighted. Once the form...
7
by: Steve | last post by:
I am building an object library for tables in a database. What is the best practice for creating objects like this? For example, say I have the following tables in my database: User: - Id -...
8
by: raylopez99 | last post by:
Hi, Best practices question. When receiving an object passed from another method, is it a good idea to use a shallow copy with a temporary object received on the RHS (right hand side of =),...
3
by: bsturg21 | last post by:
Hello, I have a windows form that has a series of linklabels on it, and I need to have each linklabel, when clicked, open a separate windows form that has a single paramter passed into it. The...
20
by: tshad | last post by:
Using VS 2003, I am trying to take a class that I created to create new variable types to handle nulls and track changes to standard variable types. This is for use with database variables. This...
0
by: DolphinDB | last post by:
Tired of spending countless mintues downsampling your data? Look no further! In this article, you’ll learn how to efficiently downsample 6.48 billion high-frequency records to 61 million...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.