Dynamically Loading Assembly and Accessing its Types (namespaces are different)

S

Smithers

Using 3.5, I am stuck in attempting to:

1. Dynamically load an assembly
2. Instantiate a class from that assembly (the client code is in a different
namespace than the namespace of the dynamically loaded assembly)

so far so good (per my code below)... but here is where I'm getting hung up:
3. Call methods of that type (see comments in my code)

If the types in the dynamically loaded assembly were in the same namespace
as the namespace of the code that does the loading, then life would be good.
I could just define an interface and implement it in the dynamically loaded
type. Then the client code could operate on the loaded type as its interface
type. But the namespaces are different (and they need to stay different -
and there cannot be a project reference to the dynamically loaded type's
project).

How do I get around that? How can I call methods of the type when (1) the
client code is in a different namespace and (2) the type gets loaded at
runtime - thus no ability to cast to the necessary type?

//*************************************************************************
string assemblyName = "CompanyNameHere.CopyFileInstaller";
string typeName = "CompanyNameHere.Installers.CopyFileInstaller"; //
includes namespace

System.Reflection.Assembly loadedAssembly =
System.Reflection.Assembly.Load(assemblyName);

Type theType = null;
theType = loadedAssembly.GetType(typeName);

object instance = null; // ultimately I don't want an object type here if
possible
if (theType != null)
{
instance = Activator.CreateInstance(theType); // this works.

// ??? what goes here so I can call methods of the CopyFileInstaller type?
// instance is of object - and I don't know how to cast to the Type
of theType.
// That type is defined a different namespace than this executing
code
// and that namespace is located in an assembly loaded only at
runtime,
// so I can't just set a project reference...
}
//*************************************************************************

Thanks!

- "Smithers"
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Smithers said:
Using 3.5, I am stuck in attempting to:

1. Dynamically load an assembly
2. Instantiate a class from that assembly (the client code is in a
different namespace than the namespace of the dynamically loaded assembly)

so far so good (per my code below)... but here is where I'm getting hung
up:
3. Call methods of that type (see comments in my code)


It has nothing to do with the namespace with rather the definition of the
interfaces of those types dynamically loaded.
If those types implement an interface known by the calling code you are ok,
you can cast the CreateInstance to the correct type.
For example if any type implement System.Windows.Form you can access it.

A possible solution in your case is to define a set of interfaces in a
separate DLL that both the calling code as the called code types implement.
Then you can access them using these interfaces.
 
S

Smithers

Hi Ignacia,
RE:
<< If those types implement an interface known by the calling code you are
ok. >>

Hummm, mybe this is coming from my ignorance, but I would think that the
whole "dynamically loading assemblies and types" features would allow for,
or even *anticipate*, that calling code would not necessarily have to know
anything about the dynamically loaded types ahead of time in order to call
methods in those types. Yes, specific Types have to be known at some point,
and I understand that most/all Type information can be discovered at
runtime...

I am just surprised that we cannot dynamically cast to a specific Type that
is discovered [by the client code] only at runtime. What good is all that
runtime discovery capability (per Assembly.GetTypes(),
Assembly.GetExportedTypes(), etc) if we can't use it without forehand
knowledge? I have assumed that's one of the major reasons to have this
discovery capability. Was I wrong?


RE:
<<A possible solution in your case is to define a set of interfaces in a
separate DLL that both the calling code as the called code types implement.
Then you can access them using these interfaces>>

Yes - I thought about something like that, but it seemed like a bit of a
hack to me given my [apparently incorrect] expectations I described in my
sentence above ("I'm am just surprised...").

-"Smithers"
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Smithers said:
Hi Ignacia,
RE:
<< If those types implement an interface known by the calling code you are
ok. >>

Hummm, mybe this is coming from my ignorance, but I would think that the
whole "dynamically loading assemblies and types" features would allow for,
or even *anticipate*, that calling code would not necessarily have to know
anything about the dynamically loaded types ahead of time in order to call
methods in those types.

It does not in fact, but if you do not know of any interface those types
implement you can only refer to them by using Object. Any other feature will
have to be discovered or called using Reflection.
Yes, specific Types have to be known at some point, and I understand that
most/all Type information can be discovered at runtime...

Again, by using Reflection.
I am just surprised that we cannot dynamically cast to a specific Type
that is discovered [by the client code] only at runtime.

you can do it, it's just that if the calling code does not know the type of
the dynamic loaded type, to what it will be cast it?
What good is all that runtime discovery capability (per
Assembly.GetTypes(), Assembly.GetExportedTypes(), etc) if we can't use it
without forehand knowledge? I have assumed that's one of the major reasons
to have this discovery capability. Was I wrong?

You have a lot of uses, even if you do not know beforehand the types. But
they all resort to use Reflection at some point.
 
S

Smithers

Thanks Ignacio... I got it to work (code below): It was your guidance to
Reflection that I was missing (a topic I no doubt have a lot to learn
about).

GetType().InvokeMember() is what did the trick.

I do notice that I didn't have to cast to any particular type in order to
make the call. I just knew there had to be a way to call a member of a
dynamically loaded type - without the client having prior knowledge of the
specific Type. I mistakenly thought that I would have to somehow cast to the
correct Type in order to invoke the members. I now understand that I must do
so, *unless* Reflection is somehow employed (which is the case with
InvokeMember()).

Thanks again.

//*************************************************
string assemblyName = "CompanyNameHere.CopyFileInstaller";
string typeName = "CompanyNameHere.Installers.CopyFileInstaller";

System.Reflection.Assembly loadedAssembly =
System.Reflection.Assembly.Load(assemblyName);

Type theType = null;
theType = loadedAssembly.GetType(typeName);

object instance = null;
if (theType != null)
{
instance = Activator.CreateInstance(theType);
string testresult = (string)
instance.GetType().InvokeMember("DoSomething",
System.Reflection.BindingFlags.InvokeMethod, null, instance, new
object[]{"Yodel"});
}
//*************************************************

-"Smithers"


Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

Smithers said:
Hi Ignacia,
RE:
<< If those types implement an interface known by the calling code you
are ok. >>

Hummm, mybe this is coming from my ignorance, but I would think that the
whole "dynamically loading assemblies and types" features would allow
for, or even *anticipate*, that calling code would not necessarily have
to know anything about the dynamically loaded types ahead of time in
order to call methods in those types.

It does not in fact, but if you do not know of any interface those types
implement you can only refer to them by using Object. Any other feature
will have to be discovered or called using Reflection.
Yes, specific Types have to be known at some point, and I understand that
most/all Type information can be discovered at runtime...

Again, by using Reflection.
I am just surprised that we cannot dynamically cast to a specific Type
that is discovered [by the client code] only at runtime.

you can do it, it's just that if the calling code does not know the type
of the dynamic loaded type, to what it will be cast it?
What good is all that runtime discovery capability (per
Assembly.GetTypes(), Assembly.GetExportedTypes(), etc) if we can't use it
without forehand knowledge? I have assumed that's one of the major
reasons to have this discovery capability. Was I wrong?

You have a lot of uses, even if you do not know beforehand the types. But
they all resort to use Reflection at some point.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

Smithers said:
Thanks Ignacio... I got it to work (code below): It was your guidance to
Reflection that I was missing (a topic I no doubt have a lot to learn
about).

Glad to be of help.
GetType().InvokeMember() is what did the trick.

I do notice that I didn't have to cast to any particular type in order to
make the call.

Well, into what you wanted it to be casted into? :)

I just knew there had to be a way to call a member of a
dynamically loaded type - without the client having prior knowledge of the
specific Type. I mistakenly thought that I would have to somehow cast to
the correct Type in order to invoke the members.

Again, there is a contradiction above, you refer to the same type as unknow
and as the correct type.
 
S

Smithers

Glad to be of help.
Well, into what you wanted it to be casted into? :)

I just knew there had to be a way to call a member of a

Again, there is a contradiction above, you refer to the same type as
unknow and as the correct type.

There is a difference between specifying a return type for a method (which
my working code does, per my last post) and specifying the Type of the
object that contains the method *prior* to invoking any of the methods
(which I now know is unnecessary per Reflection).

So, the return type of the invoked member is cast to string, in this line...

string testresult = (string) instance.GetType().InvokeMember("DoSomething",
System.Reflection.BindingFlags.InvokeMethod, null, instance, new
object[]{"Yodel"});

.... while the variable named 'instance' is declared of the object type and
is never cast (at least not by me) to the CopyFileInstaller type, which is
where the DoSomething method is implemented.


Is there still a contradiction?

-"Smithers"
 
S

Smithers

RE:
<< A possible solution in your case is to define a set of interfaces in a
separate DLL that both the calling code as the called code types implement.
Then you can access them using these interfaces.>>

I just did this and it works beautifully.

A quick followup question:
Is doing the above considered in any way to be a "hack" or somehow a "bad
thing"?

While it creates another project and .dll to maintain (as little as that
maintenance is over time), it seems to be *less* of a hack than using
Reflection (which I also got to work) - at least in my "plugin application".
I'd be interested in your thoughts on this perspective.

Thanks again.
 

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