为什么 Type.GetType() 可以工作而 Assembly.GetType() 无法工作?

6

我正在尝试从一系列程序集中在运行时定位一个类型;我的代码类似于这样:

foreach (Assembly assembly in assembliesToSearch)
{
    Type t = assembly.GetType(assemblyName);
    if (t != null)
    {
        return t;
    }
}

我的问题是t总是为null。在VS2010中,通过调试器和Intermediate窗口进行实验后,当我在循环内设置断点时发现以下情况:

Type.GetType(typeof(MyNamespace.MyClass).AssemblyQualifiedName)

运行正常,但是

assembly.GetType(typeof(MyNamespace.MyClass).AssemblyQualifiedName)

当我知道包含我要查找的类的程序集时,使用assembly.GetType()搜索该程序集为何不起作用(在调试器中,我可以在assembly.GetTypes()上设置一个监视点,浏览到我要实例化的类,并调用assembly.GetType("MyNamespace.MyClass, MyNamespace"))。

有没有人知道为什么使用Type.GetType()搜索所有程序集会起作用,但使用assembly.GetType()搜索我知道包含该类型的程序集却不起作用?

1个回答

10
从这两个方法的MSDN文档来看,Type.GetType()期望一个类型的程序集限定名称,而Assembly.GetType()则期望类型的完整名称。这两者不相同。 typeof(MyNamespace.MyClass).AssemblyQualifiedName评估为类型的程序集限定名称(类似于 MyNamespace.MyClass, MyAssembly, Version=1.0.0.0, Culture=neutral),因此它不能与期望格式为 MyNamespace.MyClass 的字符串的Assembly.GetType()调用一起使用。
这可能是因为当您将程序集限定名称传递给Assembly.GetType()调用时,它正在查找程序集中完全匹配所提供内容的类型。它找不到,所以返回了一个null。这不适用于Type.GetType()调用,因为它期望获得类型的程序集限定名称,并且可以定位程序集和类型。
需要注意的是:
如果您“尝试从程序集列表中在运行时查找类型”,正如您所说,您最好在该列表中的每个程序集上使用Assembly.GetType()调用并传入类型的完整名称。Type.GetType()很可能使用当前程序集的引用来解析类型,因此如果该类型存在于不是引用的程序集中,则无法找到它。

感谢您的回复;我的初始代码示例并没有清楚地显示出来,但在我调用Type t = assembly.GetType(assemblyName)的循环内部,assemblyName是"MyNamespace.MyClass, MyAssembly",所以按照我的估算,它应该返回期望的Type。 - David Keaveny
@David: MyNamespace.MyClass,MyAssembly 仍然是一个装配限定的类型名。你需要从该字符串中删除程序集名称才能将其与 Assembly.GetType()一起使用。 - adrianbanks
@adrianbanks - 你从哪里学到了 "Type.GetType() 很可能会使用当前程序集的引用来解析类型" 这个概念?在 MSDN 中似乎没有相关说明。另外,“当前程序集”是什么意思?在我目前研究的情况下,包含该类型的程序集已经找到了,但它并不是当前正在执行方法的程序集,也不是它的引用……但它确实在调用堆栈中。 (我提出这个问题的原因是:我的程序集名称中的版本号是错误的,但是该类型还是能够被找到。) - davidbak
我是通过思考它的工作原理来推断的。不太可能搜索每个可能的程序集(例如GAC中的每个dll以及当前应用程序路径中的每个dll),因此可以推断出程序集的引用将用于搜索路径。我认为“当前程序集”指的是包含使用Type.GetType()的类型的程序集。“但它是调用堆栈上的程序集”-所以你的意思是一个引用的引用吗?如果是这样,那么我期望会找到它,因为类型解析器将执行递归引用遍历。 - adrianbanks
@adrianbanks - 我的意思是引用方向错误...在调用堆栈上更高的程序集引用了包含调用Type.GetType()方法的类型的程序集,但反过来则不然。我想知道答案是否在《Essential .NET Volume 1》中?(这本书没有第二版或第二卷真是太遗憾了!) - davidbak
@adrianbanks - 在MSDN中有一条注释,它说“没有强名称的程序集不进行版本检查,运行时也不会在全局程序集缓存中检查没有强名称的程序集”。这解决了我的问题。谢谢! - davidbak

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