2009-08-15 11 views
4

基本クラスFooParentがあり、それには多くの量のFooChildrenがあるとします。実行時にFooChildrenのインスタンスを作成する必要があります。どうすればいい?私は巨大な地図(および代理人を使用)または巨大なswitch/caseのステートメントを作成することができたことを理解していますが、ちょっとうんざりしているようです。 PHPのようなものでは、次のようにクラスを動的に簡単に作成できます。.NETでの動的クラスの初期化

$className="FooClass"; 
$myNewFooClass=new $className; //makes a new instance of FooClass 

(これもリフレクションを使用して行うことができます)

.NETには次のようなものがありますか?反射はオプションであり、パフォーマンスには何らかの罰則がありますか?そうでない場合は、他にどのようなオプションがありますか?

JSONリクエストによってクラスのタイプが決定されます。変数は、私が望む何でもかまいません。私が列挙をしたい場合、整数にすることも、完全なクラス名にすることもできます。私はまだそれを作成していないので、私は未定です。

+0

"Activator.CreateInstance"を参照してください。 –

+0

クラスには常にパラメータのないコンストラクタがありますか? –

答えて

8

あなたが本当に欲しいのであれば、それを反映させることはできますが、パフォーマンス上の罰則があります。彼らが重要かどうかは、あなたの正確な状況に左右されます。

あなたが何をしたいのかによって、スイッチ/ケースのステートメントまたはマップのいずれかをお勧めします。特に、構築している型に基づいて異なるコンストラクタに異なる引数を渡す必要がある場合には便利です。リフレクションで行うことは、すでに別の種類の特殊なケースになっているという点では苦労します。


EDIT:これで、パラメータのないコンストラクタが常に存在することがわかりました。その場合には、(それらはすべて同じ名前空間にいる場合)あなたのJSONは簡単に名前空間なしでクラス名が含まれている可能性があり、あなたの方法は、このようなものになります:あなたが決めるん

public FooParent CreateFoo(string name) 
{ 
    if (name == null) 
    { 
     throw new ArgumentNullException("name"); 
    } 
    string fullName = "Some.NameSpace." + name; 
    // This is assuming that the type will be in the same assembly 
    // as the call. If that's not the case, we can look at that later. 
    Type type = Type.GetType(fullName); 
    if (type == null) 
    { 
     throw new ArgumentException("No such type: " + type); 
    } 
    if (!typeof(FooParent).IsAssignableFrom(type)) 
    { 
     throw new ArgumentException("Type " + type + 
            " is not compatible with FooParent."); 
    } 
    return (FooParent) Activator.CreateInstance(type); 
} 

を使用する名前は?あなたは、ちょうど私が以外(それは任意の真のメリットを持っているかわからないことを書かれた

public FooParent CreateFoo(string name) 
{ 
    switch (name) 
    { 
     case "Foo1":  return new Foo1(); 
     case "Foo2":  return new Foo2(); 
     case "Foo3":  return new Foo3(); 
     case "Foo4":  return new Foo4(); 
     case "FooChild1": return new FooChild1(); 
     default: 
      throw new ArgumentException("Unknown Foo class: " + name); 
    } 
} 

マインド:それはどこかに渡された場合は少し離れ規範から再フォーマットする場合、switch文は、非常に単純なことができパフォーマンス)をType.GetType(name)とし、次にActivator.CreateInstance(type)を使用します。

発信者は、渡すクラス名をどのように知っていますか?それは間違いなく動的でしょうか?ジェネリック薬を使用する可能性はありますか?状況について私たちに伝えるほど、役に立つかもしれません。

+0

私は少しだけもっと明確になるように私の投稿を更新しました。 – ryeguy

+0

はい、クラスには常にparamaterlessコンストラクタがあります。 – ryeguy

2
yourvar = Activator.CreateInstance(Type.GetType("foo.bar.Baz")); 
3

すべてのFooChildrenにパラメータレスコンストラクタがある限り、これを反映させることができます。あなたが実際に型への参照を持っていない、とあなたが持っているすべてのクラスの名前を持つ文字列の場合

Activator.CreateInstance<FooChildType>(); 

、あなたが行うことができます:

Activator.CreateInstance("FooChildClassName", "Fully.Qualified.AssemblyName"); 

は、パフォーマンスの低下がありますあなたのための最も簡単な解決策であると判明すれば、私はそれについて懸念するつもりはなく、あなたのパフォーマンスは受け入れられます。

0

パフォーマンスが気になる場合は、別の方法もあります。あなたのクラスのタイプを取得するには、

Type yourType = Type.GetType("FooClass"); 

を使用してください。これで、コンストラクタのコンストラクタ情報を取得するのに、

ConstructorInfo ctor = yourType.GetConstructor(new Type[0]); 

を使用できます。デフォルトコンストラクタが必要ない場合は、コンストラクタに渡す型の配列を渡します。最初の2つのステップが一度だけ実行する必要が

object instanceOfFooClass = ctor.Invoke(new object[0]); 

:今、あなたはこのようにコンストラクタを使用することができます。さらに使用するために "ctor"を保存することができます。 Activator.CreateInstanceを呼び出す方が速いはずです。

関連する問題