tags:

views:

205

answers:

4

Suppose I have a factory method, which wants to construct an instance of a type chosen at run-time via reflection. Suppose further that my factory method is generic code that doesn't directly reference the assembly that contains the specified type, though it will be run from within an application that has the necessary assembly referenced.

How do I go about writing code that can find this type? If I do the following

public object CreateInstance(string typeName)
{
    Type desiredType = Assembly.GetExecutingAssembly().GetType(typename);

    // Instantiate the type...
}

this appears to fail because the type isn't defined in the executing assembly. If I could get all the assemblies available at runtime, I could iterate over them and find which one contains the type I want. But I can't see a way to do that. AppDomain.CurrentDomain.GetAssemblies() looks promising, but doesn't return all assemblies that I've referenced in my project.

Edit: Several people have pointed out that I need to load the assembly. The trouble is, this piece of code doesn't know which assembly it should load, since I'm attempting to write this code in such a way that it does not depend on the other assemblies.

I deliberately left out the details of typeName, since the mapping from string to type is actually more complicated in my real code. In fact, the type is identified by a custom attribute that contains the specified string, but if I can get hold of a list of types, I don't have a problem with restricting the list to the desired type.

+1  A: 

AppDomain.CurrentDomain.GetAssemblies() only returns the loaded assemblies. So you need to load that referenced assembly if it has not been loaded already.

leppie
A: 

See link text for an example

Ando
+2  A: 

The call to AppDomain.CurrentDomain.GetAssemblies() only returns the set of DLLs which are currently loaded into theAppDomain. DLLs are loaded into a CLR process on demand. Hence it won't include all of the DLL`s referenced in your project until one is actually used.

What you could do though is force the assembly into the process by using a typeof expression. For example

var force1 = typeof(SomeTypeInTheProject).Assembly;
var force2 = typeof(SomeTypeInProject2).Assembly;
JaredPar
Thanks, this seems to work - and since all the possible types are in the same assembly, I only have to do it for one type. It feels rather ugly, though.
Tim
+1  A: 

You could use GetReferencedAssemblies and loop through all the types until you find the type you're looking for.

var t = Assembly
   .GetExecutingAssembly()
   .GetReferencedAssemblies()
   .Select(x => Assembly.Load(x))
   .SelectMany(x => x.GetTypes()).First(x => x.FullName == typeName);

Although it might not be the most performant. Then again, you are using reflection.

David Morton
Good idea. It doesn't quite work for me, since the assembly isn't directly referenced, but is indirectly referenced by the calling assembly; presumably I'd be able to find it by recursively calling .GetReferencedAssemblies() on each of the found assemblies (and starting from .GetEntryAssembly() rather than .GetExecutingAssembly()). And yes, it's not great for performance, but that's OK for me as it's start-up code and only run once.
Tim