Create an object by class Type reference?

G

Guest

Hi,

I have a bunch of object derived from the same base class. They all share
the same constructor with some parameters. Now, instead of using a large
switch() statement where I call every single Object by itself, I'd like to
assign a reference to the class type and call it later without knowing the
derived type.

Example:

class BaseA {
public BaseA (int aParam) {...}
}

class DerivedA {
public DerivedA(int aParam) : BaseA (aParam){ ... }
}

class DerivedB {
public DerivedB(int aParam) : BaseA (aParam){ ... }
}

and now

Something a = DerivedA;
switch(type)
{
1: a = DerivedA; break;
2: a = DerivedB; break;

}

BaseA instance = new a(5);

Is this possible? The actual parameter list is very long, so it would be
cool to do it later.

Even better: can I create get the Type by string (due some reflection
feature or something)?

Thanks
Doc
 
A

Andreas Mueller

docschnipp said:
Hi,

I have a bunch of object derived from the same base class. They all share
the same constructor with some parameters. Now, instead of using a large
switch() statement where I call every single Object by itself, I'd like to
assign a reference to the class type and call it later without knowing the
derived type.

Example:

class BaseA {
public BaseA (int aParam) {...}
}

class DerivedA {
public DerivedA(int aParam) : BaseA (aParam){ ... }
}

class DerivedB {
public DerivedB(int aParam) : BaseA (aParam){ ... }
}

and now

Something a = DerivedA;
switch(type)
{
1: a = DerivedA; break;
2: a = DerivedB; break;

}

BaseA instance = new a(5);

Is this possible? The actual parameter list is very long, so it would be
cool to do it later.

Even better: can I create get the Type by string (due some reflection
feature or something)?

Thanks
Doc

The best way to accomplish this is reflection and the Activator class:


class BaseA{
public BaseA (int aParam, double s) {}
}

class DerivedA : BaseA{
public DerivedA(int aParam, double s) : base(aParam, s) { }
}

class DerivedB : BaseA{
public DerivedB(int aParam, double s) : base(aParam, s) { }
}

class Program
{
static void Main()
{
// get a type from a string
Type derivedAType =
Type.GetType(
"ConsoleApplication.DerivedA, ConsoleApplication");

Type derivedBType = typeof (DerivedB);


// create the instances by type:

BaseA a1 =
(BaseA) Activator.CreateInstance(derivedAType, 10, 2.0);
BaseA a2 =
(BaseA)Activator.CreateInstance(derivedBType, 10, 10.0);
}
}
}

HTH,
Andy
 
G

Guest

Andreas Mueller said:
The best way to accomplish this is reflection and the Activator class:
...

Thanks. That is exactly what I tried to find. I guess, the GetType() function
returns null if the class does not exist, right?

Thanks again for the very good example.
doc
 
A

Andreas Mueller

docschnipp said:
:




Thanks. That is exactly what I tried to find. I guess, the GetType() function
returns null if the class does not exist, right?

Yes, it does.
 
J

Jeffrey Tan[MSFT]

Hi,

How about your issue now? If you still need any help, please feel free to
tell me, thanks.

Additionally, Andreas' sample code uses Reflection to create object
instance with late binding approach. Normally, late binding may have some
performance hit. The MSDN article below talks about how to get good
reflection performance and some best practice, for your information:
"Reflection--Dodge Common Performance Pitfalls to Craft Speedy Applications"
http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/default.aspx

Thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeffrey,

"Jeffrey Tan[MSFT]" said:
How about your issue now? If you still need any help, please feel free to
tell me, thanks.

In the end I decided against it since it is not supported by the .NET
Compact Framework and I tend to take care about portability in this code. I
am having
a bias for mobile devices ;) Also it is increasing the working set and I try
to keep the memory footprint of that code as small as possible.
Additionally, Andreas' sample code uses Reflection to create object
instance with late binding approach. Normally, late binding may have some
performance hit.

Thanks for pointing this out. I was vaguely aware of that and just try to
find a balance between nice code and fast code. But this clarifies my
decision.
The MSDN article below talks about how to get good
reflection performance and some best practice, for your information:
"Reflection--Dodge Common Performance Pitfalls to Craft Speedy Applications"
http://msdn.microsoft.com/msdnmag/issues/05/07/Reflection/default.aspx

It is sometimes a pity that such perls of wisdom are so hidden in all the
articles :)
Very informative writing.

thanks for that, also to andreas,
doc
 
J

Jeffrey Tan[MSFT]

Hi Doc,

Yes, I see your concern. The mobile devices really have tight concern over
performance.

Late binding technologies such as Reflection have the advantage of agility
at runtime, however, they always will sacrifice some performance since the
technologies have to lookup the runtime data structure dynamically without
the help of the compiler. I also find few artilces regarding the late
binding performance topic, however, there is finally one :)

If you need further help, please feel free to post, thanks.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeffrey,

"Jeffrey Tan[MSFT]" said:
Yes, I see your concern. The mobile devices really have tight concern over
performance.

Additionally I thought about the overall code run and switching an integer
to set a Type reference and use the Activator to create it is.. well.. I
already used an integer over a string to identify the specific class so I can
call the constructor directly. These 30 lines of switch() { case n: result =
new NClass() ...} aren't soo ugly that it is okay to sacrifice performance so
much.
Late binding technologies such as Reflection have the advantage of agility
at runtime, however, they always will sacrifice some performance since the
technologies have to lookup the runtime data structure dynamically without
the help of the compiler. I also find few artilces regarding the late
binding performance topic, however, there is finally one :)

Anyway, I was coming from Delphi to C++ and now C# is such a relief when I
have to write something that must "getting done". But I am still paranoid
about what happens under the hood, simple instructions can be really
expensive in way, especially when someone is using a lot of "shlemiel the
painter" algorithms in the code. And Reflection is actually such a thing.

Thanks for your help, I really appreciated it,

best
doc
 
J

Jeffrey Tan[MSFT]

Hi Doc,

Thanks for the feedback.

I am assuming you are using an integer value(like enum type) in switch to
identiy different class type, so that you can call the class constructor
directly. Yes, this is another approach of resolving this runtime type
identification problem. Since compiler will generate the switch/case map at
compile time, it will save time for query the type information at runtime
as Reflection does. The extra time of looking up the type identity moves
from Reflection runtime to compile time, so the runtime performance will
increase.

Yes, .Net/C# does a lot magic under the hood and it is much more complex
than win32 programming. I recommend book "Applied .Net Framework
Programming" by Jeffrey Richter if you want to learn the .Net internal from
developer's perspective. Another good resource is book "Shared Source CLI
Essentials", it explains the "Shared Source CLI" project maintained by
Microsoft. This project is a sample implementation of .Net, including both
CLR and Framework Class Library. With this project, you have a sample
source code of .Net :) Actually, I always use it to learn .Net internals.

You may download SSCLI project in the link below:
"Shared Source Common Language Infrastructure 2.0 Release"
http://www.microsoft.com/downloads/details.aspx?FamilyId=8C09FD61-3F26-4555-
AE17-3121B4F51D4D&displaylang=en

Hope this helps.

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
J

Jeff Louie

Doc.. I think you are asking about a class factory that returns a
specific object
from a domain of classes that shares a base class or interface. The
classic class
factory returns on an integer switch so that a subclass can extend the
class
factory. You can also use an enum for safety but this is hard coded and
not
extensible.

If you want a dynamic growable class factory you can use a type based
class
factory that uses reflection or an interface based class factory. The
interface
based class factory takes an object of type IMyClassFactory that
provides a
method Instantiate() which returns an object of MyBaseClass or
MyCommonInterface. The class factory is implemented as a wrapper to a
hashtable of objects so lookup is based on a key.

Regards,
Jeff
I have a bunch of object derived from the same base class.
 
J

Jeffrey Tan[MSFT]

Yes, on pattern level, this is called class factory :)

Best regards,
Jeffrey Tan
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
G

Guest

Hi Jeff,

Jeff Louie said:
Doc.. I think you are asking about a class factory that returns a
specific object
from a domain of classes that shares a base class or interface. The classic class
factory returns on an integer switch so that a subclass can extend the
class factory.

The integer is actually not an enum. My project is a DICOM library and I use
classes for the different Value Representations. These VRs are encoded in the
stream with 2 bytes like 'U','L' for "unsigned long value" or 'D','A' for a
"date value". I am reading it as an integer (bigendian read) and use these
integer values to use the correct class that handles the specific properties
of the encoded values. All unknown VRs fall into a default class that handles
them.

So I don't need to extend it at runtime since I would need to write new
classes to handle new elements.
You can also use an enum for safety but this is hard coded and
not
extensible.

See above, extensible at compile time is okay.
If you want a dynamic growable class factory you can use a type based
class
factory that uses reflection or an interface based class factory. The
interface
based class factory takes an object of type IMyClassFactory that
provides a
method Instantiate() which returns an object of MyBaseClass or
MyCommonInterface. The class factory is implemented as a wrapper to a
hashtable of objects so lookup is based on a key.

The current implementation uses a factory function the returns an object of
type DataElement, the base class to the specialized ones. I thought about
using Reflection to create a type, since the constructor is somewhat
complicated with all the parameters, but since Activator is not in the
Compact Framework (see my other posts in this thread) I decided against it.
So for now it is fast, maybe not that elegant, but portable.

thanks for your suggestions,
doc
 
J

Jeff Louie

Hi Jeffrey... I added a reference to your link to two chapters in my oop
tutorial.
Thanks for the heads up.

Regards,
Jeff
 
J

Jeff Louie

Doc... Glad to hear you got it to work.

The advantage of using an int or computed value as you are doing is that
it is
possible for another programmer to subclass your code if your class
factory is
declared virtual. So if you have a switch for argument sake from int 1
to 5,
another programmer can subclass your code and override the virtual class
factory. The programmer could then intercept codes from 6 to say 10 and
pass
any other parameters to the base class class factory reusing your code.
In all
probability this is totally not applicable to your situation, but may
help others.

Regards,
Jeff
 

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