tags:

views:

63

answers:

2

How do I obtain an instance of a Type class for a type not defined in the currently executing assembly or in mscorlib.dll?

a) Namely, I've defined a class type someType in assembly CSharpSnapIn.dll, located at E:\CSharpSnapIn.dll, but for some reason when I try to specify an absolute path to this assembly, I get an exception:

Type t = Type.GetType("someType, E:\\CSharpSnapIn.dll"); // exeception

b) I've also tried by putting CSharpSnapIn.dll into \bin\debug directory of a currently running application, but I still get an exception:

Type t = Type.GetType("someType, CSharpSnapIn.dll"); // exeception

thanx

EDIT:

1) I've declared another class type someType2 ( inside CsharpSnapIn.dll )and this time it worked:

Type.GetType("someType2, CSharpSnapIn");

Difference between someType and someType2 is that someType implements an interface declared in external assembly asmIn, but this shouldn't cause an exception, since CsharpSnapIn.dll does have a reference to asmIn?!

2)

Note that the assembly doesn't need to be loaded first, so long as the assembly resolver can find it

In other words, calling Type.GetType() first loads an assembly and then creates a Type instance?

3)

The assembly has to be found by probing, so it would have to be in the bin directory as per your second example. If it's an assembly with a strong name, you have to give all the details.

So you're saying we can't specify an absolute path ( to an assembly ) using Type.GetType(), but instead assembly needs to reside inside a bin directory?

+4  A: 

You need to give the assembly name - not the file which contains it.

For example:

Type t = Type.GetType("someType, CSharpSnapIn");

The assembly has to be found by probing, so it would have to be in the bin directory as per your second example. If it's an assembly with a strong name, you have to give all the details. Note that someType here also has to be fully qualified in terms of the namespace.

Note that the assembly doesn't need to be loaded first, so long as the assembly resolver can find it. For example, if the assembly is in the same directory as the currently executing assembly, that will be fine in most cases.

As Darin says, an alternative is to load the assembly directly - although in my experience there are quite a few "gotchas" in loading assemblies explicitly, particularly if you've got two assemblies in different locations which both rely on a third assembly. Making sure you only get that third assembly loaded once can be tricky.

You need to choose between LoadFile and LoadFrom etc. Here are some remarks from MSDN:

Use the LoadFile method to load and examine assemblies that have the same identity, but are located in different paths. LoadFile does not load files into the LoadFrom context, and does not resolve dependencies using the load path, as the LoadFrom method does. LoadFile is useful in this limited scenario because LoadFrom cannot be used to load assemblies that have the same identities but different paths; it will load only the first such assembly.

Jon Skeet
Could you see EDIT in my original post?
flockofcode
I'm pretty sure that if you use Type.GetType(assemblyAualifiedName) you can pass an absolute file path for the assembly name
Rune FS
@Rune FS, I am pretty sure you can't. As @Jon said, for `Type.GetType` to work the assembly needs to be resolved by the standard probing heuristics used by the CLR (for example if the assembly is located in the `bin` folder for an ASP.NET application or in the same folder as the executable for a Console and WinForms application).
Darin Dimitrov
@flockofcode: Yes, unless you explicitly load the assembly first from a different directory, it has to be in one of the probed folders.
Jon Skeet
1) "...unless you explicitly load the assembly first from a different directory..." By explicitly loading an assembly you mean by calling Assembly.LoadFrom? 2) Any idea why someType implementing an interface causes an exception when calling Type.GetType()?
flockofcode
@flockofcode: 1) Yes. 2) Without knowing the exception, it's tricky... but I'm going to guess that the interface is in a different assembly, and the CLR doesn't know where to load that assembly from.
Jon Skeet
"2) Without knowing the exception, it's tricky... but I'm going to guess that the interface is in a different assembly, and the CLR doesn't know where to load that assembly from." Yes, interface is in different assembly than someType ( someType is declared in CSharpSnapIn.dll), but since CSharpSnapIn.dll has a reference to the assembly where this interface is declared, Type.GetType() shouldn't cause an exception?!
flockofcode
@flockofcode: Yes it will, because when the prober tries to load the interface, it doesn't use the location of the referring type's assembly.
Jon Skeet
What do you mean it doesn't use the location? Why couldn't the prober ( which I assume is called by Type.GetType ) check with CSharpSnapIn.dll where the location of interface's assembly is and load it from that location?
flockofcode
@flockofcode: I suppose it could, but that could have other consequences around security etc. Anyway, whether you want it to or not, it doesn't.
Jon Skeet
Just one more question - so that means that whenever we try to obtain a Type instance ( via Type.GetInstance ) for a type T declared in an external assembly, then if T implements an interface declared in some external assembly asmExt, or if T's base class is declared in asmExt, then a call to Type.GetType will always fail?
flockofcode
@flockofcode: If that assembly can't be loaded, then I'd expect so. You *might* be able to do it if you load the assembly for reflection only.
Jon Skeet
I'm not sure I understand what you mean by "load it for reflection only"?
flockofcode
@flockofcode: Look at the API for loading assemblies - some of the calls are "reflection only" - i.e. you don't want to run the code in the assemblies, just read the metadata.
Jon Skeet
+5  A: 

You will need to first load the assembly:

Type t = Assembly
    .LoadFrom(@"e:\CSharpSnapIn.dll")
    .GetType("SomeNs.SomeType", true);
Darin Dimitrov