2017-03-17 115 views
4

我有一個公共抽象類Client與兩個繼承類CustomerTimeWaster組合框項目顯示解決方案中的類名稱

我在C# Windows Forms上創建了一個下拉菜單,我想將這兩個類名稱顯示爲選項:Customer & TimeWaster。

所有我能想到的是創建一個簡單的List包含這兩個條款,然後在列表綁定到組合框DataSource

List<string> clientType = new List<string>() 
{ 
    "Customer", 
    "TimeWaster" 
}; 

public frmClientScreen() 
{ 
    cmboxClientType.DataSource = clientType; 
} 

但這不是維護,因爲在將來,我可能添加許多其他我希望在下拉菜單中顯示的名稱的類。

如何將我的Visual Studio Solution中的類名稱鏈接到組合框顯示的項目?

+1

你正在談論「類型發現」,而且要走的路是反思。看看這個問題:http://stackoverflow.com/questions/2362580/discovering-derived-types-using-reflection – Ishmaeel

+0

@Ishmaeel謝謝!類型的發現和反思對我來說是新的,所以我必須學習一個全新的概念。歡呼 – Joshua

回答

3

爲了得到一組已知的類型的類型名稱:

List<string> clientType = new List<string>() 
{ 
    nameof(Customer), 
    nameof(TimeWaster) 
}; 

public frmClientScreen() 
{ 
    cmboxClientType.DataSource = clientType; 
} 

至於動態獲取從一個特定的類型派生的所有類型,這question顯示瞭如何做到這一點的例子。

從這個問題接受的答案:

var listOfBs = (from domainAssembly in AppDomain.CurrentDomain.GetAssemblies() 
       from assemblyType in domainAssembly.GetTypes() 
       where typeof(B).IsAssignableFrom(assemblyType) 
       select assemblyType).ToArray(); 

B應與你的基類來代替。

然後,漸漸派生類型的列表之後,你可以做到以下幾點:

var clientTypes = listOfBs.Select(x => x.Name).ToList(); 
+0

非常感謝。爲了查看輸出,我把這段代碼放在'Main'中,但是它不返回任何東西,數組長度回到零。我的類可以在我的'Main'中看到,所以我想知道這個代碼是否可以放在任何地方? – Joshua

+1

主要的是,許多程序集可能尚未加載,因爲.Net使用「即時加載」。也就是說,程序集在使用之前不會被加載。主要的是,大多數程序集可能還沒有加載,所以你得到一個空數組並不奇怪。 –

+0

明白了,謝謝。 – Joshua

2

我不得不這樣做了許多不同的時間,到了那裏我只是想一個全局函數點我可以使用。所以,我清理了一些常見的來源代碼,並結束了:

public static class ReflectionHelper 
{ 
    public static List<T> GetAllNonabstractClassesOf<T>() 
    { 
     Object[] args = new Object[0]; 
     return GetAllNonabstractClassesOf<T>(args); 
    } 

    public static List<T> GetAllNonabstractClassesOf<T>(Object[] args) 
    { 
     List<T> retVal = new List<T>(); 
     IEnumerable<object> instances = from t in Assembly.GetExecutingAssembly().GetTypes() 
             where t.IsSubclassOf(typeof(T)) && !t.IsAbstract 
             select Activator.CreateInstance(t, args) as object; 
     foreach (T instance in instances) 
     { 
      retVal.Add(instance); 
     } 
     return retVal; 
    } 
} 

...然後,你可以簡單地調用這樣的代碼:

List<myClass> = ReflectionHelper.GetAllNonabstractClassesOf<myClass>(); 

(或類中是否需要構造函數的參數,你可以使用第二個函數。)

無論如何,它的美妙之處在於,無論你想通過多少種不同的類來反映,你只需要通過你的代碼一次就可以使用這個函數。

+0

這是天才!非常感謝你。 – Joshua

+1

請注意,這隻會加載當前程序集中的類。如果您在不同的程序集中定義基類的子類,那麼將不會使用此方法檢索它。 –