Loading Generic Types with Assembly.LoadFrom

I thought I’d write up a question I posed today on StackOverflow here: Loading a generic type using Assembly.LoadFrom

I had a pre-existing method that I use to get a type based on a full assembly path and a class name. This resides in a Utils namespace.

public Type GetTypeOf(string assemblyPath, string className)
{
    var asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath); //open assembly 
    return asmbly.GetType(className, true, true); //throws error, not case sensitive
}
Public Function GetTypeOf(ByVal assemblyPath As String, ByVal className As String) As Type
    Dim asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath)
    Return asmbly.GetType(className, True, True)
End Function

I was hoping to use this as follows:

string genName = "MyNamespace.Generic";
string itemName = "System.String";

//Get the types
var genTyp = GetTypeOf(genPath,genName);
var itemTyp = GetTypeOf(itemPath,itemName);

//Put them together:
var typ = getType.MakeGenericType(itemTyp);
Dim genName = "MyNamespace.Generic"
Dim itemName = "System.String"

Dim genTyp = GetTypeOf(genPath,genName)
Dim itemTyp = GetTypeOf(itemPath,itemName)

Dim typ = getType.MakeGenericType(itemTyp)

This falls over on the first line with a System.TypeLoadException stating:

Could not load type <TypeName here> from assembly <AssemblyName here>

I tried a number of permutations of the Generic and Item types, for example MyNamespace.Generic<System.String>

Solution

The answer, as suggested by Carsten on the SO question, is that the item type needs to use the fully qualified name to be loaded.

The example Carsten gave was in this format:

TestType`1[[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]

Using this template I setup a different version of GetTypeOf, which I named GetGenericTypeOf just to make its purpose clear:

public Type GetGenericTypeOf(string assemblyPath, string genericClass, string itemQualifiedClass)
{
    string typString = String.Format("{0}`1[[{1}]]",genericClass,itemQualifiedClass);
    var asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath); //open assembly
    return asmbly.GetType(typString, true, true); //throws error, not case sensitive
}
Public Function GetGenericTypeOf(ByVal assemblyPath As String, ByVal className As String, ByVal itemQualifiedClass as string) As Type
    Dim typString = String.Format("{0}`1[[{1}]]",genericClass,itemQualifiedClass)
    Dim asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath)
    Return asmbly.GetType(typString , True, True) 
End Function

This new function is then applied in conjunction with the original to get all the information required to create an instance of the generic type:

//Get the types of the item and the generic
var itemTyp = GetTypeOf(itemPath,itemName);
var genTyp = GetGenericTypeOf(genPath,genName,itemTyp.AssemblyQualifiedName);

//This genTyp is then good to go: 
var genInst = Activator.CreateInstance(genTyp);
Dim itemTyp = GetTypeOf(itemPath,itemName);
Dim genTyp = GetGenericTypeOf(genPath,genName,itemTyp.AssemblyQualifiedName);

var genInst = Activator.CreateInstance(genTyp);

Leave a Reply

Your email address will not be published.

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax

This site uses Akismet to reduce spam. Learn how your comment data is processed.