使用Assembly.LoadFrom加载通用类型

4

参考Jon Skeet在这里的答案:将已实例化的System.Type作为泛型类的类型参数传递

我需要根据泛型类型的名称和作为泛型类型参数的类型的名称来加载泛型类型。所以从Jon的示例中,我会有:

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

我有以下的代码,它将根据类型的名称和完全合理的程序集名称/路径加载类型。它对于“简单类型”可以正常工作。

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
}

我希望您能够将此用于以下方面:
//Get the types
var genTyp = GetTypeOf(genPath,genName);
var itemTyp = GetTypeOf(itemPath,itemName);

//Put them together:
var typ = getType.MakeGenericType(itemTyp);

这会在第一行出现 System.TypeLoadException,错误信息为:
Could not load type <TypeName here> from assembly <AssemblyName here>

我尝试了许多种方法来创建泛型对象,其中一种是提供完整的类名,例如MyNamespace.Generic<System.String>。当我从包含该泛型类型的程序集中加载非泛型类型时,它可以正常工作。


通常情况下,是否可以加载genType程序集所依赖的所有程序集? - Maarten
是的,我能够毫无问题地从genType的程序集中加载一个非泛型类。 - Jon Egerton
2个回答

4

很遗憾,使用GetType与泛型类型不够直观易读。您必须使用完全限定的类型名称,即使是泛型参数:例如,TestType<object> 的读法如下:

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

您的示例代码没有包含类型声明,因此您需要对其进行调整。您可以尝试这个代码片段,并查看调试器的输出:

string typeName = typeof(MyNamespace.Generic<>).Name;
string fullTypeName = typeof(MyNamespace.Generic<>).FullName;

结果应该帮助您获取正确的类型名称。

非常感谢 - 这让我找到了正确的方向。请查看我的答案以获取最终修复。 - Jon Egerton

3

根据Carsten上面的答案,我已经调整了我的GetTypeOf方法,如下:

    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
    }

我可以按照以下方式使用它:
var itemTyp = GetTypeOf(itemPath,itemName);
var genTyp = GetGenericTypeOf(genPath,genName,itemTyp.AssemblyQualifiedName);

//This genTyp is then good to go:
var genInst = Activator.CreateInstance(getTyp);

不需要使用MakeGenericType,因为返回的genType跳过了这一步。

我已经在我的博客here中写了一个完整的版本,包括VB.Net代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接