Wie instanziiere ich eine Klasse anhand ihres Stringnamens?


71

Ich habe eine abstrakte Klasse und möchte sie zu einer Klasse initialisieren, die sie erweitert.

Ich habe den Namen der untergeordneten Klassen als Zeichenfolge.

Außerdem ...

String childClassString;
MyAbstractClass myObject;

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

Wie kann ich das machen? Grundsätzlich, wie werde ich die if-Anweisungen hier los?

Antworten:


126

Schauen Sie sich Activator.CreateInstance () an.

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

oder

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

7
Lief wie am Schnürchen. Falls jemand Probleme hat, den vollständig qualifizierten Namen zu erhalten, ist dieser Code hilfreich. 'String typex = typeof (Klassenname) .AssemblyQualifiedName;
Sanjit Misra

Obwohl in der GetTypeDokumentation zu seinem typeNameParameter "Der Assembly-qualifizierte Name des Typs" angegeben ist, müssen Sie den Assembly-Namen nicht angeben. Wenn sich der Typ in der aufrufenden Assembly befindet, ist nur der für den Namespace qualifizierte Typname ausreichend.
Edward Brey

21

Ich glaube, das sollte funktionieren:

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

Der nullParameter im ersten Parameter ist standardmäßig die aktuell ausgeführte Assembly. Weitere Informationen: MSDN

bearbeiten: vergessen zu besetzen MyAbstractClass


5

Ich hatte einige Schwierigkeiten, einige der Antworten hier zu implementieren, weil ich versuchte, ein Objekt aus einer anderen Assembly zu instanziieren (aber in derselben Lösung). Also dachte ich, ich würde posten, was ich für die Arbeit gefunden habe.

Erstens weist die Activator.CreateInstanceMethode mehrere Überladungen auf. Wenn Sie nur aufrufen Activator.CreateInstance(Type.GetType("MyObj")), wird davon ausgegangen , dass das Objekt in der aktuellen Assembly definiert ist, und es wird a zurückgegeben MyObj.

Wenn Sie es wie in den Antworten hier empfohlen aufrufen Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), gibt es stattdessen ein zurück ObjectHandle, und Sie müssen es aufrufen Unwrap(), um Ihr Objekt zu erhalten. Diese Überladung ist nützlich, wenn Sie versuchen, eine in einer anderen Assembly definierte Methode aufzurufen (Übrigens können Sie diese Überladung in der aktuellen Assembly verwenden, lassen Sie einfach den AssemblyNameParameter null).

Nun stellte ich fest, dass der obige Vorschlag, typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName für AssemblyNameden ich ihn verwenden sollte, tatsächlich Fehler verursachte, und ich konnte das nicht zum Laufen bringen. Ich würde bekommen System.IO.FileLoadException(konnte Datei oder Baugruppe nicht laden ...).

Was ich zur Arbeit gebracht habe, ist wie folgt:

var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.