为什么GetType()在通过方法组委托调用时无法找到类型?

时间:2016-02-29 14:23:46

标签: c# reflection

我们有一个非常简单的程序来调用Type.GetType静态方法。两个示例都应返回有效的类型实例。实际上只有第二个。 GetType使用的堆栈抓取看起来有些奇怪,但问题到底是什么?它是错误还是一些模糊的功能?

public class TestClass { }

class Program
{
    static void Main(string[] args)
    {
        var fullName = typeof(TestClass).FullName;
        Console.WriteLine("Full name: {0}", fullName);

        new[] { fullName }.Select(Type.GetType).ToList().ForEach(t => Console.WriteLine("Method group: '{0}'", t));
        new[] { fullName }.Select(t => Type.GetType(t)).ToList().ForEach(t => Console.WriteLine("Closure: '{0}'", t));
    }
}

运行:

Full name: GetTypeBeingWeird.TestClass
Method group: ''
Closure: 'GetTypeBeingWeird.TestClass'

1 个答案:

答案 0 :(得分:165)

这真的很有趣。它是Type.GetType(string)在调用程序集方面的行为以及方法组转换的工作方式的混合。

首先,Type.GetType文档包括:

  

如果 typeName 包含命名空间而不包含程序集名称,则此方法只按顺序搜索调用对象的程序集和Mscorlib.dll。

在您的第一个电话中,您传递了一个调用Type.GetType的代理人......但是并不是从您的程序集中特别调用它。它有效地从LINQ中的Select方法直接调用 ...如果你从Type.GetType中查看堆栈跟踪,你就会看到{ {1}}作为直接来电者,我相信。

在第二次通话中,您传递了一个调用Select的闭包,并且该调用位于您的程序集中。

这就是为什么它在第二种情况下找到的类型而不是第一种情况。通过指定LINQ程序集中的类型进一步验证:

Type.GetType

然后结果是相反的:

var fullName = typeof(Enumerable).FullName;

如果您在mscorlib中指定了某些内容(例如Full name: System.Linq.Enumerable Method group: 'System.Linq.Enumerable' Closure: '' ),则这两种方法都有效:

typeof(string).FullName

在寻找你的类时仍然使用方法组来解决这种奇怪的方法只是提供组件限定的名称:

Full name: System.String
Method group: 'System.String'
Closure: 'System.String'