Casting 'object' to "real/useful" Type

R

Robert

I'm working on a plug-in architecture whereby my application dynamically
loads assemblies based on runtime conditions.

I plan to use Activator.CreateInstance to instantiate objects from the
dynamically loaded assemblies. Activator.CreateInstance of course returns
the created type as 'object'. I therefore need to cast that returned
'object' to the real type that I want (e.g., MyDal, and not 'object' - where
MyDal is a class).

My question (yes, I think there ARE dumb questions - and this might be
one! - but here goes):

Why does the application that calls Activator.CreateInstance need to know
_at compile time_ the specific Type to convert the 'object' to? It makes
perfect sense to me that the application would have to _somehow_ know ahead
of time the definition of the class type named MyDal in order to cast
'object' variables to MyDal.

I am just hung up on the fact that that knowledge has to come [apparently to
me] via a static reference (project reference). Doesn't Reflection provide
us with a way to accomplish this without a static reference?

Why can't we use Reflection to equip an application with the ability to cast
an 'object' to it's "useful type" (e.g., MyDal) -- so that the application
that is calling Activator.CreateInstance can itself, at compile time, _not_
know anything about the MyDal type (a class), and instead acquire that
knowledge at runtime. Ideally, the application could somehow cast 'object'
types to "real types" without having any compile-time knowledge of the "real
type."

What am I missing?

Thanks in advance.
 
G

George Ter-Saakov

You need to read up on "Interfaces"

Example:
interface ISampleInterface
{
void SampleMethod();
}

class ImplementationClass : ISampleInterface
{
void ISampleInterface.SampleMethod()
{
}

static void Main()
{
ISampleInterface obj = new ImplementationClass();
obj.SampleMethod();
}
}

so let say you have bunch of dynamically loaded objects... And they all
support interface ISampleInterface.
So application casts your object to ISampleInterface and calls it's methods.

Thus application does not need to know ahead of time of the class
ImplementationClass. The only requirement is that
it knows about ISampleInterface.
So the usual practice to compile interfaces into separate DLL and your
application only reference that DLL (to know about interace) And your
dynamicly loaded object will need to reference the same DLL to be able to
implement that interface.

George.
 
S

sloan

To follow up on this post:

http://sholliday.spaces.live.com/Blog/cns!A68482B9628A842A!126.entry

Get that downloadable code, and look at the "reflection based simple factory
pattern".

...




George Ter-Saakov said:
You need to read up on "Interfaces"

Example:
interface ISampleInterface
{
void SampleMethod();
}

class ImplementationClass : ISampleInterface
{
void ISampleInterface.SampleMethod()
{
}

static void Main()
{
ISampleInterface obj = new ImplementationClass();
obj.SampleMethod();
}
}

so let say you have bunch of dynamically loaded objects... And they all
support interface ISampleInterface.
So application casts your object to ISampleInterface and calls it's
methods.

Thus application does not need to know ahead of time of the class
ImplementationClass. The only requirement is that
it knows about ISampleInterface.
So the usual practice to compile interfaces into separate DLL and your
application only reference that DLL (to know about interace) And your
dynamicly loaded object will need to reference the same DLL to be able to
implement that interface.

George.


Robert said:
I'm working on a plug-in architecture whereby my application dynamically
loads assemblies based on runtime conditions.

I plan to use Activator.CreateInstance to instantiate objects from the
dynamically loaded assemblies. Activator.CreateInstance of course returns
the created type as 'object'. I therefore need to cast that returned
'object' to the real type that I want (e.g., MyDal, and not 'object' -
where MyDal is a class).

My question (yes, I think there ARE dumb questions - and this might be
one! - but here goes):

Why does the application that calls Activator.CreateInstance need to know
_at compile time_ the specific Type to convert the 'object' to? It makes
perfect sense to me that the application would have to _somehow_ know
ahead of time the definition of the class type named MyDal in order to
cast 'object' variables to MyDal.

I am just hung up on the fact that that knowledge has to come [apparently
to me] via a static reference (project reference). Doesn't Reflection
provide us with a way to accomplish this without a static reference?

Why can't we use Reflection to equip an application with the ability to
cast an 'object' to it's "useful type" (e.g., MyDal) -- so that the
application that is calling Activator.CreateInstance can itself, at
compile time, _not_ know anything about the MyDal type (a class), and
instead acquire that knowledge at runtime. Ideally, the application could
somehow cast 'object' types to "real types" without having any
compile-time knowledge of the "real type."

What am I missing?

Thanks in advance.
 
R

Robert

Thanks George, I really am grateful for attempts to be helpful, but this
really doesn't answer the question in my OP.

What I am looking for is an explanation of WHY things are this way (I was
not looking for a work-around).

Again, I am appreciative of the feedback. I will note, that even though I
can use Interfaces, the calling application and the dynamically loaded
assembly both need compile-time refrences to the assembly that contains the
interfaces (as you accurately pointed out). This does not answer the core
question I have about the need to have compile-time references.

Again, the question is all about an explanation of WHY we must have
compile-time references... and why Reflection cannot get us around that
apparent requrement.

-Robert
 
J

Jeff Louie

Robert.. You can use interfaces or an abstract base class to abstract
out the
functionality of the plug ins. You then program to the abstraction. In
the case
of an interface, you program to the public view, the interface. The
interface
defines a contract between the user of your plug in class and any
concrete
implementation of the class. The caller programs to the type. The caller
does
not need to know the class of the object only that the object implements
the
type. The class, however, is discoverable at runtime.

http://www.geocities.com/jeff_louie/OOP/oop13.htm
http://www.geocities.com/jeff_louie/OOP/oop37.htm

A common example of using plug ins is a menu. You can place your plugins
in a plugins folder and dynamically load the types at runtime and then
dynamically populate the menu at runtime. When the user selects a
concrete
implementation from the menu, you can instantiate the concrete class
using
a type based factory method.

public IDrawableShape GetInstance(string key)
{
...
else
{
Type t= (Type)hash[key];
// dynamically load this class
return (IDrawableShape)Activator.CreateInstance(t);
//else return null;
}
}

http://www.geocities.com/jeff_louie/OOP/oop18.htm

The problem with this approach is that concrete types known at _compile
time_ are also late bound in this approach. So a better approach is to
use
inheritance to create a hierarchy of class factories. Classes know at
compile
time are created using early binding and classes discovered at runtime
are
created using late binding.

http://www.geocities.com/jeff_louie/OOP/oop35.htm

Regards,
Jeff
 
J

Jon Skeet [C# MVP]

Robert said:
Thanks George, I really am grateful for attempts to be helpful, but this
really doesn't answer the question in my OP.

What I am looking for is an explanation of WHY things are this way (I was
not looking for a work-around).

Again, I am appreciative of the feedback. I will note, that even though I
can use Interfaces, the calling application and the dynamically loaded
assembly both need compile-time refrences to the assembly that contains the
interfaces (as you accurately pointed out). This does not answer the core
question I have about the need to have compile-time references.

Again, the question is all about an explanation of WHY we must have
compile-time references... and why Reflection cannot get us around that
apparent requrement.

If you're willing to make *all* the calls via reflection, then you can
indeed work completely without any other references.
 
S

sloan

You must have a compile time reference TO THE INTERFACE.
This is why the interface library should be stand alone...and you can put
the concrete's anywhere you'd like.

If you follow my example, it will show you ( I believe ) a non compile time
reference.

.....

as my example shows:

<rateQuoterObject enabled="true"
assemblyName="GranadaCoder.Applications.FactoryPatternExamples.ConcreteObjectsOutsideBaseAssembly"
className="GranadaCoder.Applications.FactoryPatternExamples.ConcreteObjectsOutsideBaseAssembly.ConcreteRateQuoters.UPSRateQuoter"
ShippingCompanyHomeState="NC"/>

I have a "Quoter" that isn't referenced. Or at least, doesn't need to be
referenced.

...


DotNet has to know ~at least~ about the interface if you want it to return
something other than object.
 
I

Ignacio Machin ( .NET/ C# MVP )

Thanks George, I really am grateful for attempts to be helpful, but this
really doesn't answer the question in my OP.

What I am looking for is an explanation of WHY things are this way (I was
not looking for a work-around).

Again, I am appreciative of the feedback. I will note, that even though I
can use Interfaces, the calling application and the dynamically loaded
assembly both need compile-time refrences to the assembly that contains the
interfaces (as you accurately pointed out). This does not answer the core
question I have about the need to have compile-time references.

Again, the question is all about an explanation of WHY we must have
compile-time references... and why Reflection cannot get us around that
apparent requrement.

-Robert

Hi,

You do not need add a refeence at compile time if you load all your
dlls using Assembly.Load() and call members using reflection.
It's a slow and convoluted way of doing it, but you can do it.
 
I

Ignacio Machin ( .NET/ C# MVP )

Why can't we use Reflection to equip an application with the ability to cast
an 'object' to it's "useful type" (e.g., MyDal) -- so that the application
that is calling Activator.CreateInstance can itself, at compile time, _not_
know anything about the MyDal type (a class), and instead acquire that
knowledge at runtime. Ideally, the application could somehow cast 'object'
types to "real types" without having any compile-time knowledge of the "real
type."

What am I missing?

The difference between compile & runtime. CreateInstance works at
runtime, you can pass ANY string to it (even an incorrect one like
"123123123123") and it will compile
Only at runtime you will get the error.
And honestly, you HAVE to know something about your Class. otherwise,
how do you know which method to call?
 
G

George Ter-Saakov

I think I understood now...
What you want is called late binding.
You can do that. I heard it's easier done in VB.NET than in C#. Google it.

The only thing I do not understand is what you are trying to do. To do
something meaningful you need to know what kind of object you working with.
Even if you do not want to do "early binding" via interface you need to know
what this object doing....

Obviously, in order to call the object, you need to know what methods it
supports... Let say it has "RunMe" method.. Are you just going to call it?
My guess you expected this object to have that method... But then why not to
have it in interface and use early binding?



The interface
George.
 
B

bruce barker

its because the .net runtime is strongly typed. to call a method or access a
property, the type of the object must be known at compile time. the major
workaround is as suggested using interfaces.

other languages (javascript, ruby, python, object-c, smalltalk, etc) support
dynamic binding, which allows your code to just call the method.

even java (which is also strongly typed) supports runtime re-compiles so
that plugins and remoting will work the way you expect. this feature was left
out of .net for various performance reasons.

..net now has a dlr (dynamic language runtime) that supports this behavior,
but you need to use a dlr language like IronPython, IronRuby or managed
JScript.


-- bruce (sqlwork.com)
 
R

Robert

Thank you Bruce for answering my specific question. I have a Quick followup
question:

Is it true then [given your response] that I _cannot_ do step 3 of the
following sequence from my C# application:

1. load an .NET assembly via Reflection - where my application has
absolutely no compile-time knowledge of the assembly or the types within
that assembly (i.e., no project reference to the assembly). This step, by
itself, is obviously easy to do using Reflection.

2. use Reflection to identify the types within that assembly. This step, by
itself, is obviously easy to do using Reflection.

3. instantiate a class of a specific type from within that assembly. This
step, given steps 1 and 2 above cannot happen, and for the reasons you
gave - yes?

For example, MyApp is a C# app that loads the Some3rdParty assembly, which
is a .NET assembly that contains a class named Frapper. Apparently because
the .NET runtime is strongly typed, MyApp _cannot_ create a Frapper instance
_unless_ MyApp also has a compile-time reference to the Some3rdParty
assembly. Is this correct, and for the reasons you stated?

I'm asking this because I want to verify that I understand your response.

Please note that I'm not asking about the merits of doing this, and I'm not
attempting to solve some problem "the hard way". My interest is mostly
academic... just wanting to understand things more clearly, and particularly
to find out if my understanding is incorrect. FWIW, I have already done a
couple of plug-in apps that go with the interface-based recommendations
others have made elsewhere in this thread. I'm clear on that... I just want
to know why, and I think I do now - provided that I understand your
response.

Thanks.
 
G

Gilles Kohl [MVP]

Robert,

Thank you Bruce for answering my specific question. I have a Quick followup
question:

Is it true then [given your response] that I _cannot_ do step 3 of the
following sequence from my C# application:

1. load an .NET assembly via Reflection - where my application has
absolutely no compile-time knowledge of the assembly or the types within
that assembly (i.e., no project reference to the assembly). This step, by
itself, is obviously easy to do using Reflection.

2. use Reflection to identify the types within that assembly. This step, by
itself, is obviously easy to do using Reflection.

3. instantiate a class of a specific type from within that assembly. This
step, given steps 1 and 2 above cannot happen, and for the reasons you
gave - yes?

For example, MyApp is a C# app that loads the Some3rdParty assembly, which
is a .NET assembly that contains a class named Frapper. Apparently because
the .NET runtime is strongly typed, MyApp _cannot_ create a Frapper instance
_unless_ MyApp also has a compile-time reference to the Some3rdParty
assembly. Is this correct, and for the reasons you stated?

No - consider this sample MyApp:

namespace MyApp
{
class Program
{
static void Main(string[] args)
{
Assembly assembly =
Assembly.LoadFrom(@"c:\tmp\Some3rdParty\bin\Debug\Some3rdParty.dll");

Type frapperType = assembly.GetTypes().Where(t => t.Name ==
"Frapper").SingleOrDefault();

if(frapperType == null)
{
Console.WriteLine("Out of frappers");
return;
}

MethodInfo frappitMethod = frapperType.GetMethods().Where(m
=> m.Name == "Frappit").SingleOrDefault();
if(frappitMethod == null)
{
Console.WriteLine("Frapper can't frap it");
return;
}

object frapperInstance =
Activator.CreateInstance(frapperType);
string result = (string)frappitMethod.Invoke(frapperInstance,
new object[0]);

Console.WriteLine(result);
}
}
}

it will attempt to load "Some3rdParty.dll", find any class called
"Frapper", locate a method "Frappit" in that class (which hopefully
returns a string and doesn't have any parameters), and call it.

Here's Frapper

namespace Some3rdParty
{
public class Frapper
{
public string Frappit()
{
return "Greetings, Pr. Falken";
}
}
}

This works without any reference from the MyApp project to the
Some3rdParty project containing the Frapper class.

Regards,
Gilles.
 
R

Robert

<Snip>

Thank you Gilles. Apparently my understanding was incorrect. It really helps
to see and study the sample code that you so kindly provided.

-Robert
 
H

Hans Kesting

Robert expressed precisely :
I'm working on a plug-in architecture whereby my application dynamically
loads assemblies based on runtime conditions.

I plan to use Activator.CreateInstance to instantiate objects from the
dynamically loaded assemblies. Activator.CreateInstance of course returns the
created type as 'object'. I therefore need to cast that returned 'object' to
the real type that I want (e.g., MyDal, and not 'object' - where MyDal is a
class).

My question (yes, I think there ARE dumb questions - and this might be one! -
but here goes):

Why does the application that calls Activator.CreateInstance need to know _at
compile time_ the specific Type to convert the 'object' to? It makes perfect
sense to me that the application would have to _somehow_ know ahead of time
the definition of the class type named MyDal in order to cast 'object'
variables to MyDal.

I am just hung up on the fact that that knowledge has to come [apparently to
me] via a static reference (project reference). Doesn't Reflection provide us
with a way to accomplish this without a static reference?

Why can't we use Reflection to equip an application with the ability to cast
an 'object' to it's "useful type" (e.g., MyDal) -- so that the application
that is calling Activator.CreateInstance can itself, at compile time, _not_
know anything about the MyDal type (a class), and instead acquire that
knowledge at runtime. Ideally, the application could somehow cast 'object'
types to "real types" without having any compile-time knowledge of the "real
type."

What am I missing?

Thanks in advance.


Activator.CreateInstance *does* create the specific Type it was
requested to do, only it returns it cast to an 'object'. It doesn't
matter that the assembly that contains that type was not available
during compilation (but it needs to be available during runtime).

BUT if you want to call some methods or access some properties of that
object, then the compiler will want to know something about that
'object'. That is why you need to cast it to something. Usually this
means casting to some baseclass or interface that contains those
methods/properties you want to use, instead of the specific "real"
type.

Hans Kesting
 

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