web-dev-qa-db-ja.com

文字列名を指定してクラスをインスタンス化するにはどうすればよいですか?

抽象クラスがあり、それを拡張するクラスに初期化したい。

文字列として子クラス名があります。

これに加えて...

String childClassString;
MyAbstractClass myObject;

if (childClassString = "myExtenedObjectA")
    myObject = new ExtenedObjectA();
if (childClassString = "myExtenedObjectB")
    myObject = new ExtenedObjectB();

これどうやってするの?基本的に、ここでifステートメントを削除するにはどうすればよいですか?

63
ctrlShiftBryan

Activator.CreateInstance()を見てください。

myObject = (MyAbstractClass)Activator.CreateInstance("AssemblyName", "TypeName");

または

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
112

私はこれがうまくいくと信じています:

myObject = (MyAbstractClass)Activator.CreateInstance(null, childClassString);

最初のパラメータのnullは、デフォルトで現在実行中のアセンブリになります。詳細なリファレンス: [〜#〜] msdn [〜#〜]

編集:MyAbstractClassへのキャストを忘れました

20
IAbstract

別のアセンブリからオブジェクトをインスタンス化しようとしていたので、ここでいくつかの答えを実装するのに多少の困難がありました(同じソリューション内)。だから、私は自分が見つけたものを投稿すると思った。

まず、_Activator.CreateInstance_メソッドにはいくつかのオーバーロードがあります。 Activator.CreateInstance(Type.GetType("MyObj"))を呼び出すだけの場合、オブジェクトは現在のアセンブリで定義されていると想定し、MyObjを返します。

Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName)の回答で推奨されているように呼び出すと、代わりにObjectHandleを返します。オブジェクトを取得するには、Unwrap()を呼び出す必要があります。このオーバーロードは、別のアセンブリで定義されたメソッドを呼び出そうとするときに役立ちます(ところで、現在のアセンブリでこのオーバーロードを使用できますが、AssemblyNameパラメーターはnullのままにしてください)。

さて、AssemblyNametypeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedNameを使用するという上記の提案は実際にエラーを引き起こし、それを機能させることができなかったことがわかりました。 _System.IO.FileLoadException_を取得します(ファイルまたはアセンブリをロードできませんでした...)。

私が仕事に就いたのは次のとおりです。

_var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
_
5
Kevin Fichter