2017-03-17 10 views
4

私は公開クラスが2つあるCustomerTimeWasterの公開抽象クラスClientを持っています。ComboBoxソリューション内にクラス名を表示するアイテム

C# Windows Formsに、これらの2つのクラス名をオプション:顧客& 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はそれを行う方法の一例を示しています。 Bがあなたのベースクラスに置き換えてください

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

:その質問で受け入れの回答から

その後、派生型のリストを取得した後、次の操作を実行できます

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

多くのありがとう。出力を見るためにこのスニペットを 'Main'に入れますが、配列の長さが0に戻って何も返しません。私のクラスは私の '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>(); 

(またはあなたのクラスはコンストラクタ引数を必要としていた場合2番目の関数を使うことができます)。

とにかく、この関数は、どれだけ多くの異なるクラスを反映させようと、コードから一度だけ必要です。

+0

これは天才です!どうもありがとうございました。 – Joshua

+1

これは、現在のアセンブリ内にあるクラスのみをロードすることに注意してください。別のアセンブリで基本クラスの子クラスを定義すると、このメソッドでは取得されません。 –

関連する問題