2010-02-18 24 views
5

假設我有一個工廠方法,它想要構建在運行時通過反射選擇的類型的實例。進一步假設我的工廠方法是通用代碼,它不直接引用包含指定類型的程序集,儘管它將從具有必要程序集引用的應用程序中運行。如何通過反射從引用的程序集中獲取類型

我該如何着手編寫可以找到這種類型的代碼?如果我做了以下

public object CreateInstance(string typeName) 
{ 
    Type desiredType = Assembly.GetExecutingAssembly().GetType(typename); 

    // Instantiate the type... 
} 

這似乎失敗,因爲該類型未在執行的程序集定義。如果我可以在運行時獲得所有可用的程序集,我可以遍歷它們並找出哪一個包含我想要的類型。但我看不出有辦法做到這一點。 AppDomain.CurrentDomain.GetAssemblies()看起來很有前途,但不會返回我在項目中引用的所有程序集。

編輯:有幾個人指出我需要加載程序集。麻煩的是,這段代碼不知道應該加載哪個程序集,因爲我試圖以不依賴於其他程序集的方式編寫代碼。

我故意省略typeName的細節,因爲從字符串到類型的映射實際上在我的真實代碼中更加複雜。實際上,類型是由包含指定字符串的自定義屬性標識的,但是如果我可以獲取類型列表,那麼將列表限制爲所需類型時不存在問題。

+0

typeName中的值是什麼?這是完全合格的名字嗎? – 2010-02-18 18:50:02

回答

9

AppDomain.CurrentDomain.GetAssemblies()的調用僅返回當前加載到AppDomain中的一組DLL。根據需要將DLL加載到CLR進程中;因此在實際使用之前,它不會包含項目中引用的所有DLL。

你可以做什麼,是通過使用typeof表達式強制程序集進入過程。例如

var force1 = typeof(SomeTypeInTheProject).Assembly; 
var force2 = typeof(SomeTypeInProject2).Assembly; 
+0

謝謝,這似乎工作 - 因爲所有可能的類型都在同一個程序集中,我只需要爲一種類型。不過,這感覺相當難看。 – 2010-02-18 19:05:39

2

AppDomain.CurrentDomain.GetAssemblies()只返回加載的程序集。所以你需要加載引用程序集,如果它尚未加載。

10

您可以使用GetReferencedAssemblies並遍歷所有類型,直到找到所需的類型。

var t = Assembly 
    .GetExecutingAssembly() 
    .GetReferencedAssemblies() 
    .Select(x => Assembly.Load(x)) 
    .SelectMany(x => x.GetTypes()).First(x => x.FullName == typeName); 

雖然它可能不是最高性能的。然後再次,你使用反射。

+0

好主意。它不適合我,因爲程序集不是直接引用的,而是被調用程序集間接引用;大概我能找到它遞歸調用.GetReferencedAssemblies()在每個找到的程序集(並從.GetEntryAssembly(),而不是.GetExecutingAssembly())。是的,這對性能並不是很好,但對我來說這沒問題,因爲它是啓動代碼,只能運行一次。 – 2010-02-18 20:57:14

相關問題