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)
{
//open assembly
var asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath);
//throws error, not case sensitive
return asmbly.GetType(className, true, true);
}
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
from assembly
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);
//open assembly
var asmbly = System.Reflection.Assembly.LoadFrom(assemblyPath);
//throws error, not case sensitive
return asmbly.GetType(typString, true, true);
}
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,
temTyp.AssemblyQualifiedName);
//This genTyp is then good to go:
var genInst = Activator.CreateInstance(genTyp);
Dim itemTyp = GetTypeOf(itemPath,itemName);
Dim genTyp = GetGenericTypeOf(genPath,genName,
temTyp.AssemblyQualifiedName);
var genInst = Activator.CreateInstance(genTyp);