2011-12-20 17 views
4

私は基本的な抽象クラスをいくつか持っていますが、それを拡張してオーバーライドしますが、それらはすべて同じコンストラクタを持っています。今私はswitch文から各コンストラクタを呼び出します:クラスのインスタンス化を抽象化

など、約10クラスです。ジェネリックスやデリゲートがクラス名を取り、その型を引数でインスタンス化するメソッドを作る方法はありますか?

私はコンストラクタを変更すると、各インスタンス化も変更する必要があるので、これは役に立ちます。

代議員は最も簡単ですが、リサーチは委任者にコンストラクタを割り当てることはできません。

追加: 私のノートパソコンではなく、ノートパソコンで無線LANに接続していますので、ここにコードがあります。

これは今、何が起こるかの例です:

switch (new Random().Next(4)) 
{ 
    case 3: 
     // classA : baseClass, args{int, bool, otherClass} 
     return new classA(arg1, arg2, arg3); 
    case 2: 
     // classB : baseClass, args{int, bool, otherClass} 
     return new classB(arg1, arg2, arg3); 
    case 1: 
     // classC : baseClass, args{int, bool, otherClass} 
     return new classC(arg1, arg2, arg3); 
    case 0: 
     // classD : baseClass, args{int, bool, otherClass} 
     return new classD(arg1, arg2, arg3); 
    default: 
     continue; 
} 

私は三つの引数を持つブロックの最後に1つのインスタンス化を呼び出すしたいと思います。私が考え

ソリューションは、これに似た働きクラスを作成し、インスタンシすることです:

ClassInstantiator inst = new ClassInstantiator(arg1, arg2, arg3); 
switch(new Random().Next(4)) 
{ 
    case 4: 
     return inst.instantiate<classA>(); 
    ... 
} 

は、すでに言語に組み込まれてこれは、以上のエレガントなソリューションの人を知っているのですか?

+0

+1大きな質問です。 –

+0

アクティベーターが私が上で部分的に説明した技術であるとさらに考えた後、私は実現する。 – kskid19

答えて

5

あなたはジェネリック型に置くことができる唯一のコンストラクタ関連の制約は、公共のパラメータなしのコンストラクタを必要とnew()制約、です。

リフレクションを使用できます。例では、すべての関連のタイプがあなたの例のように、int型を取るコンストラクタを持っている、と抽象基底クラスがBと呼ばれていることをことを前提としています

A a = CreateInstance<A>(3); 

public T CreateInstance<T>(int i) where T : B 
{ 
    return (T)Activator.CreateInstance(typeof(T), i); 
} 

次に、あなたがこのようにそれを呼びたいです

+0

私をそれに打つ、phoog。 +1。 –

+1

また、実際に 'new()'制約を使用すると、 'new'と言うときはいつでも、' Activator.CreateInstance'へのコンパイラ生成の呼び出しを得ることに注意してください。 –

5

何かを条件付きで決定する必要がありますが、それをカプセル化することはできません。あなたに最も人気のあるGOFパターンの1つをお伝えください:http://en.wikipedia.org/wiki/Factory_method_pattern

public abstract class MyBase(string name){} 
public class Concrete1 : MyBase{} 
public class Concrete2 : MyBase{} 

public class MyFactory 
{ 
    public MyBase Create(Criteria criteria) 
    { 
     //conditional logic/reflection 
    } 
} 
+0

基本的には、インスタンス化したいクラスごとに別のクラスがありますか?...問題は、それぞれのcaseステートメントで同じ引数を使用して呼び出すことができなくなります。たとえば、クラス名Aを変数に格納してから、変数を使用してメソッドを呼び出して、共通の引数で目的のクラスをインスタンス化することができます。 – kskid19

+0

いいえ、基底型を返す単一のメソッドの中に具体的な型の選択をカプセル化する単一のクラスがあります。これには、選択の基準として何かを渡す必要があります。あなたはそのタイプを言いました、あなたはそれを使うことができました(この場合、反射は理想的な@phoogかもしれません)、またはドメイン固有の基準がもう一つあるかもしれませんか? –

0

私はあなたの問題を複雑にするわけではありませんが、この種のコードがたくさんあるとわかったら、IoCコンテナを使用することに興味があります。

人気のIoCコンテナ:

+0

私はあなたに同意していませんが、それ以上説明できますか?これらのコンテナは、コンストラクタのarg型に依存して異なるconcretesをインスタンス化することができますか? –

+1

@MylesMcDonnell私が質問を理解しているように、ロジックはコンストラクタのarg型以外のもので条件付きです(「それらはすべて同じコンストラクタを持っている」とは、コンストラクタがすべて同じ型のパラメータを同じ数持つことを意味します)。 – phoog

+0

はい、そうです、私の上記のコメントはこの質問の文脈ではナンセンスでした。 argの具体的な型に応じて具体的な実装を選択できるコンテナがあれば、私は興味がありますか?私はそこにいると思うし、ジェネリック薬が有効な要因だと私は期待している。 –

1

クラス名をキーとしてコンストラクタを値として委譲して辞書を作成できます。

Dictionary<string,Func<int,BaseClass>> _dict = new Dictionary<string,Func<int,BaseClass>>(); 
_dict.Add("ClassA", i => new ClassA(i)); 
_dict.Add("ClassB", i => new ClassB(i)); 

// Create ClassA object by class name 
BaseClass obj = _dict["ClassA"](5); 
関連する問題