文字列からクラスのインスタンスを作成する


217

実行時にクラスの名前がわかっているという事実に基づいて、クラスのインスタンスを作成する方法はありますか?基本的に、クラスの名前は文字列で記述します。


実装したいソリューションを説明しているようですが、解決しようとしている問題は説明していません。おそらく、拡張性を備えた何かをしようとしている場合は、Managed Extensibility Frameworkを確認することをお勧めします。
ジェイバズジ

回答:


159

Activator.CreateInstanceメソッドを見てください。


15
優れた例に関連して: stackoverflow.com/questions/493490/…–
John S.

また、あなたのタイプを見つける必要があるため、この投稿も関連します。stackoverflow.com
Brad Parks


4
例:var driver = (OpenQA.Selenium.IWebDriver)Activator.CreateInstance("WebDriver", "OpenQA.Selenium.Firefox.FirefoxDriver").Unwrap();
Endy Tjahjono 2014年

2
ここでの重要な注意:キャストを実行できるように、リモートハンドルを通過する.Unwrap()。@Endy-ありがとう
ロジャーウィルコックス

77

とてもシンプルです。クラス名がCarでネームスペースがVehiclesであると想定し、Vehicles.Carタイプのオブジェクトを返すパラメータを渡しますCar。このようにして、任意のクラスの任意のインスタンスを動的に作成できます。

public object GetInstance(string strFullyQualifiedName)
{         
     Type t = Type.GetType(strFullyQualifiedName); 
     return  Activator.CreateInstance(t);         
}

あなたの場合は完全修飾名(すなわち、Vehicles.Carこの場合は)別のアセンブリであり、Type.GetTypenullになります。このような場合、すべてのアセンブリをループしてを見つけますType。そのためには、以下のコードを使用できます

public object GetInstance(string strFullyQualifiedName)
{
     Type type = Type.GetType(strFullyQualifiedName);
     if (type != null)
         return Activator.CreateInstance(type);
     foreach (var asm in AppDomain.CurrentDomain.GetAssemblies())
     {
         type = asm.GetType(strFullyQualifiedName);
         if (type != null)
             return Activator.CreateInstance(type);
     }
     return null;
 }

ここで、パラメーター化されたコンストラクターを呼び出す場合は、次のようにします。

Activator.CreateInstance(t,17); // Incase you are calling a constructor of int type

の代わりに

Activator.CreateInstance(t);

キャストせずにそれを使用する方法と、与えられた文字列からキャストする方法は?
TaW '25

1
@TaW-クラスインスタンスを使用するためには、クラスインスタンスが何をするかについてある程度の知識が必要です-そうしないと、クラスインスタンスを使用できません。これの最も一般的な使用例は、事前定義されたコントラクトを提供するインターフェイスにキャストすることです。(これは、あなたが使用している場合を除き保持しているdynamic-を参照してコードをstackoverflow.com/a/2690661/904521を
Tomer Cagan

1
その名に変数の型をコードしない、例えば:プレフィックスする必要はありませんstrFullyQualifiedNameとはstrfullyQualifiedName仕事をするだろう。
Mehdi Dehghani

キーワードstrは、変数の命名規則の一部として使用されます。特定の組織やプロジェクトはこれに従うよう主張しているので、私はそれを使用しました。特定の組織/プロジェクトで働いていたなら、あなたはこれを知るでしょう。あなたが言わなくてstrもそれは仕事をします:) @MehdiDehghani
Sarath Avanavu

1
命名規則について知っておく必要はありませんが、この表記法ハンガリー語の表記法として知られています。これは、世の中で非推奨の悪い命名規則の1つです。特にC#向け
Mehdi Dehghani '15 / 12/15

55

私はこの方法をうまく使いました:

System.Reflection.Assembly.GetExecutingAssembly().CreateInstance(string className)

返されたオブジェクトを目的のオブジェクトタイプにキャストする必要があります。


9
クラス名を使用してオブジェクトを作成し、その型としてキャストしてもまったく意味がないシナリオを想像しようとしています。
MusiGenesis 2008年

13
どういう意味かわかります。冗長なようです。クラス名がわかっている場合、動的な文字列が必要なのはなぜですか?1つの状況として、基本クラスへのキャストと文字列がその基本クラスの子孫を表す場合があります。
レイ・リー

4
基本クラスがわかっている場合は、基本クラスまたはそのインターフェイスを引数として使用して、リフレクションなしで子孫を渡すことができます。
Garet Claborn 2014年

3
便利なシナリオ:必要なのは、シリアル化インターフェイス、またはその他の非常に一般的なインターフェイスだけです。あなたはそれをクラスにキャストしませんが、少なくともオブジェクト以上のものにキャストします
Harald Coppoolse

2
指定れた文字列からキャストする方法は?
TaW、

23

おそらく私の質問はもっと具体的だったはずです。私は実際に文字列の基本クラスを知っているので、それを次のようにして解決しました:

ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

Activator.CreateInstanceクラスには、同じことを異なる方法で実現するためのさまざまなメソッドがあります。オブジェクトにキャストすることもできますが、上記は私の状況に最も役立ちます。


4
質問セクションで回答するのではなく、質問を編集して変更を記録することをお勧めします。あなたはそれを行うためのより/より良い答えを得るでしょう。
Jason Jackson、

あなたのために働いたコードの特定の行を投稿してくれてありがとう。すべてのCreateInstanceオーバーロードとタイプを生成するためのさまざまな方法を並べ替えると、多くの時間がかかりました。
Ethel Evans

4

私はゲームに遅れていることを知っています...しかし、あなたが探している解決策は、上記の組み合わせと、インターフェイスを使用してオブジェクトをパブリックにアクセスできる側面を定義することかもしれません。

次に、この方法で生成されるすべてのクラスがそのインターフェースを実装する場合、インターフェースタイプとしてキャストし、結果のオブジェクトを操作できます。


4

ソリューションの別のプロジェクトからクラスのインスタンスを作成するには、任意のクラスの名前(BaseEntityなど)で示されるアセンブリを取得して、新しいインスタンスを作成します。

  var newClass = System.Reflection.Assembly.GetAssembly(typeof(BaseEntity)).CreateInstance("MyProject.Entities.User");

3

たとえば、データベースフィールド(文字列として保存)にさまざまなタイプの値を保存し、タイプ名(String、bool、int、MyClass)を持つ別のフィールドがある場合、そのフィールドデータから、おそらく、上記のコードを使用して任意のタイプのクラスを作成し、最初のフィールドの値を入力します。もちろん、これは、文字列を正しい型に解析するメソッドを持つ、格納する型に依存します。これを何度も使用して、ユーザー設定をデータベースに保存しました。


-11
ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));

なぜあなたはこのようなコードを書きたいのですか?'ReportClass'クラスが利用可能な場合は、以下に示すように直接インスタンス化できます。

ReportClass report = new ReportClass();

コード ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass));は、必要なクラスを使用できないが、インスタンス化またはメソッドを動的に呼び出したい場合に使用されます。

私はあなたがアセンブリを知っているときに便利ですが、コードを書いている間はクラスをReportClass利用できません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.