Get type information from another assembly

M

Michi Henning

Hi,

I'm stuck on a reflection problem. Here is an outline
of what's happening

// In A.exe:

class A
{
// ...
System.Type t = System.Type.GetType("A"); // Works fine
}

// In assembly B, used by A.exe:

// ...
System.Type t = System.Type.GetType("A"); // Returns null

The problem is that GetType() finds a type only if it is
in the calling object's assembly or in mscorlib.dll. But, in
this case, the type is defined in A.exe but has to be looked
up in assembly B.

I can't find a way to make this work. I know that I can call

ProcessModuleCollection mc = Process.GetCurrentProcess().Modules;

This gets me all the modules that are loaded by the
current process. However, I can't work out a way to get the list
of assemblies that are loaded by the current process, so I could
search them one by one for a definition of the type I need.

In Java, what I'm trying to do works just fine, even if the type
I'm looking for is defined in a different jar file.

Is there any way to do this in C#?

Thanks,

Michi.
 
J

Jon Skeet [C# MVP]

Michi Henning said:
I'm stuck on a reflection problem. Here is an outline
of what's happening

// In A.exe:

class A
{
// ...
System.Type t = System.Type.GetType("A"); // Works fine
}

// In assembly B, used by A.exe:

// ...
System.Type t = System.Type.GetType("A"); // Returns null

The problem is that GetType() finds a type only if it is
in the calling object's assembly or in mscorlib.dll. But, in
this case, the type is defined in A.exe but has to be looked
up in assembly B.

Indeed - although if you give the *full* name of the type (including
assembly name, version etc) it will load all this up.
I can't find a way to make this work. I know that I can call

ProcessModuleCollection mc = Process.GetCurrentProcess().Modules;

This gets me all the modules that are loaded by the
current process. However, I can't work out a way to get the list
of assemblies that are loaded by the current process, so I could
search them one by one for a definition of the type I need.

You can get the list of all assemblies loaded in the current AppDomain
with AppDomain.GetAssemblies. However, bear in mind that unless you've
already used a type in assembly B, it may not have been loaded yet - so
you'll need to also use Assembly.GetReferencedAssemblies() on an
appropriate assembly (or even recursively) and load up whichever one
you think the type is in.
 
M

Michi Henning

Jon Skeet said:
Indeed - although if you give the *full* name of the type (including
assembly name, version etc) it will load all this up.

Right. But I don't know what the full name of the assembly is.
Basically, the code that needs to look up the type is in a generic
library, but the type is created by the application in an arbitrary
assembly that cannot be known a priori.
You can get the list of all assemblies loaded in the current AppDomain
with AppDomain.GetAssemblies. However, bear in mind that unless you've
already used a type in assembly B, it may not have been loaded yet - so
you'll need to also use Assembly.GetReferencedAssemblies() on an
appropriate assembly (or even recursively) and load up whichever one
you think the type is in.

Thanks for that info, that's really useful! I guess I'll have to try all
of the assemblies simply because I cannot know which one the
type is defined in (if it is defined at all). I guess caching of types
that I have located (or failed to locate) in the past will help
to avoid repeated searches.

Thanks a lot for your help!

Cheers,

Michi.
 
M

Michi Henning

Jon said:
Michi Henning said:
The problem is that GetType() finds a type only if it is
in the calling object's assembly or in mscorlib.dll. But, in
this case, the type is defined in A.exe but has to be looked
up in assembly B.
[...]

However, I can't work out a way to get the list
of assemblies that are loaded by the current process, so I could
search them one by one for a definition of the type I need.


You can get the list of all assemblies loaded in the current AppDomain
with AppDomain.GetAssemblies. However, bear in mind that unless you've
already used a type in assembly B, it may not have been loaded yet - so
you'll need to also use Assembly.GetReferencedAssemblies() on an
appropriate assembly (or even recursively) and load up whichever one
you think the type is in.

OK, I did all this and it works fine, thanks!

One question though: why does GetType() behave as it does?
It seems that searching only in the calling object's assembly
and mscorlib.dll isn't very useful. After all, if I want to do
reflection, I generally don't know (or care) in which assembly
a type is defined and, if I'm writing generic libraries, I cannot
possibly know what assembly a type is defined in.

So, why does Type.GetType() behave as it does?

Would it make sense to change Type.GetType() to search all assemblies?
Or maybe provide an alternate version of GetType() that does this?

Thanks,

Michi.
 
J

Jon Skeet [C# MVP]

Michi Henning said:
OK, I did all this and it works fine, thanks!

One question though: why does GetType() behave as it does?
It seems that searching only in the calling object's assembly
and mscorlib.dll isn't very useful. After all, if I want to do
reflection, I generally don't know (or care) in which assembly
a type is defined and, if I'm writing generic libraries, I cannot
possibly know what assembly a type is defined in.

Well, reflection *is* often useful within the existing assembly, and
for GetType to load all the referenced assemblies would be a big
performance hit for those who didn't want that behaviour.
So, why does Type.GetType() behave as it does?

Would it make sense to change Type.GetType() to search all assemblies?
Or maybe provide an alternate version of GetType() that does this?

An overload which did that would be useful, yes.
 
M

Michi Henning

Jon Skeet said:
Well, reflection *is* often useful within the existing assembly, and
for GetType to load all the referenced assemblies would be a big
performance hit for those who didn't want that behaviour.

Right. Loading all the assemblies isn't cheap. But, on the
other hand, I would have thought that looking at the calling object's
assembly is not very useful? After all, I would expect to have
static knowledge of the types within my own assembly, so there
would rarely (never?) be a need to look up a type in the current
assembly, I would think. After all, I use reflection to do something
with types I do *not* have static knowledge of...
An overload which did that would be useful, yes.

Well, if you have a "todo" list, it would be nice to add this.

Cheers,

Michi.
 
J

Jon Skeet [C# MVP]

Michi Henning said:
Right. Loading all the assemblies isn't cheap. But, on the
other hand, I would have thought that looking at the calling object's
assembly is not very useful? After all, I would expect to have
static knowledge of the types within my own assembly, so there
would rarely (never?) be a need to look up a type in the current
assembly, I would think. After all, I use reflection to do something
with types I do *not* have static knowledge of...

No, there are certainly times when you do reflection within the same
assembly - particularly for serialization, I suspect.
Well, if you have a "todo" list, it would be nice to add this.

I'm sure MS does, but I'm not part of MS!
 
B

bdelia

I would also suggest that reflection is commonly used in the same
assembly when using factory patterns to instantiate classes, of
different types that either inherit from a base class or implement a
common interface, dynamically.
 

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