2008-11-17 49 views
15

我有一組類,每一個都是不同的strategy做同樣的工作。創建一個只知道類名的對象?

namespace BigCorp.SuperApp 
{ 
    public class BaseClass { } 
    public class ClassA : BaseClass { } 
    public class ClassB : BaseClass { } 
} 

要使用的策略選擇是可配置的。我只想在app.config文件中配置類名'ClassB'而不是完整類型名'BigCorp.SuperApp.ClassB'。

<appConfig> 
    <SuperAppConfig> 
     <Handler name="ClassB" /> 
    </SuperAppConfig> 
</appConfig> 

然而,反射調用失敗,因爲他們預計全類型名,特別是

Type t = Type.GetType("ClassB"); // results in t == null 
BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails 

我怎樣才能得到這個工作,而只配置類的名字嗎?將名稱空間連接到完整類型名稱的類名稱?是否有另一個反射電話有效?

如果您認爲這是無用的,我應該期望配置包含完整的類型名稱,我願意接受該解決方案!只是提供理由來說服我。

(我不會從這個裝配/名稱空間外裝型)

+0

我可以使用IoC容器,處理長名稱,併爲我完成對象創建! – 2009-12-01 14:02:56

回答

6

既然你知道所有的類都來自同一個命名空間中來,一旦其配置和使用:

<appConfig> 
    <SuperAppConfig handlerNamespace="BigCorp.SuperApp"> 
     <Handler class="ClassB" /> 
    </SuperAppConfig> 
</appConfig> 

編輯:我改變更好地代表的含義該屬性。

+0

我很欣賞裝配加載的答案,代碼和討論。但我喜歡布賴恩的重點配置答案(因爲我不能脫離完整的類型名稱)。 – 2008-11-17 21:43:30

18

既可以使用集限定名,或獲得大會的持有和使用Assembly.GetType(name)。在這種情況下,由於要在配置文件中的類型,集限定是去一個有效的方式 - 但因爲你知道你所有的類型都在同一組件:

Assembly assembly = typeof(SomeKnownType).Assembly; // in the same assembly! 
Type type = assembly.GetType(name); // full name - i.e. with namespace (perhaps concatenate) 
object obj = Activator.CreateInstance(type); 

靜態Type.GetType(string)已經探測規則這經常會引起混淆......它會查看調用程序集和幾個系統程序集 - 但不是所有加載的程序集。

+0

我有一個服務引用,我想用它調用它,但它不會顯示在程序集的類型列表中(由類創建)。儘管我可以通過調用構造函數的硬編碼來創建引用的對象。 – MrFox 2015-09-22 14:00:55

5
(I will not be loading a type from outside this assembly/namespace)

因爲上面的這一行,所以假設你知道命名空間是什麼是安全的。你不能這樣做:如果你希望可能能夠增加在將來被加載額外的策略類,或許通過附加組件

Type t = Type.GetType("Namespace." + className); 
BaseClass c = Activator.CreateInstance(t) as BaseClass; 

,則需要完全限定類名。無論如何,建議您這樣做,因爲您可以爲您的應用程序提供增強的可擴展性。

+0

這實際上取決於代碼的位置(以及如何解釋「來自外部」 - 即是類還是調用者?)。如果沒有程序集限定的名稱,Type.GetType(string)將只查看當前程序集和一些系統程序集。它不會在隨機引用的dll中找到類型。 – 2008-11-17 17:47:54

2

我正在使用應用程序配置中的完整類型名稱。下面是一個稍微完整,但還是簡單的例子

<SuperAppConfig> 
    <ObjectConfig provider="BigCorp.SuperApp.ClassA"> 
     <add name="one" /> 
     <add name="two" /> 
    </ObjectConfig> 
</SuperAppConfig> 

而實際創建工廠類此

private static Assembly a = typeof(IFactoryObject).Assembly; 
public static IFactoryObject CreateObject(String providerName) 
{ 
    Type t = a.GetType(providerName) 
    IFactoryObject o = Activator.CreateInstance(t) as IFactoryObject; 
    return o; 
} 
1
BaseClass c = Activator.CreateInstance(t) as BaseClass; // fails 

也可以從這樣的事實結果,的CreateInstance不返回實例的BaseClass,而不是包裝到ObjectHandle中的BaseClass實例。

使用UnWrap方法後投射到您的BaseClass中。

相關問題