2016-02-29 46 views
144

我們有一個非常簡單的程序調用Type.GetType靜態方法。這兩個示例都應返回有效的類型實例。實際上只有第二個。看起來像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' 
+0

可能是我應該關閉較舊的?不知道,歡迎對此發表意見... – nawfal

回答

165

這真的很有趣。這是Type.GetType(string)在調用程序集方面的行爲的混合體,以及方法組轉換如何工作。

首先,Type.GetType文檔包括此:

如果的typeName包括命名空間,但不集名稱,此方法只搜索調用對象的組裝的Mscorlib.dll,按照這個順序。

在您的第一個電話中,您傳遞了一個委託,該委託調用Type.GetType ...但它不是特別從您的程序集中調用。它有效地直接調用從LINQ的Select方法...如果你從Type.GetType內看着堆棧跟蹤,你會看到Select作爲直接調用者,我相信。

在你的第二個電話,你傳遞中調用Type.GetType封閉,並調用您的組件中。

這就是爲什麼它發現在第二種情況下的類型,但不是第一個。

var fullName = typeof(Enumerable).FullName; 

然後,結果是輪相反的方式:

Full name: System.Linq.Enumerable 
Method group: 'System.Linq.Enumerable' 
Closure: '' 

如果指定在mscorlib程序的東西(例如typeof(string).FullName)則兩個這是通過指定一個類型,是在LINQ組件進一步驗證進行工作:

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

尋找你的類,仍然使用方法組來解決這個怪事的方法是簡單地提供裝配質量ified name改爲:

var fullName = typeof(TestClass).AssemblyQualifiedName; 
+16

哇,使用調用程序集作爲隱藏輸入是可怕的。有趣的錯誤,但。 – usr

+5

使用調用程序集,而不是進入或執行作爲默認可能(我確信是一個故意的決定)。我能想到的一個原因是,如果入口/執行程序集聲明瞭與mscorelib匹配的相同名稱空間和類型名稱,則在mscorelib對Type.GetType()的調用中避免類型欺騙。一個人的「藏身之處」是另一個人沒有通過標準的圖書館劫持把他的屁股交還給他。 – Serjx86

+5

API不應將任何*程序集作爲隱藏輸入。它應該由調用者指定。使用入口組件幾乎同樣糟糕。沒有程序集名稱的類型名稱很簡單。沒有好的消歧策略可能。 – usr

相關問題