Erstellen einer Instanz einer Klasse aus einer Zeichenfolge


168

Gibt es eine Möglichkeit zum Erstellen einer Instanz einer Klasse basierend auf der Tatsache, dass ich den Namen der Klasse zur Laufzeit kenne. Grundsätzlich würde ich den Namen der Klasse in einer Zeichenfolge haben.

137

Werfen Sie einen Blick auf die Activator.CreateInstance Methode.

+14

Verwandten mit großen Beispielen nennen wollen: http : //stackoverflow.com/questions/493490/converting-a-string-to-a-class-name 24 apr. 132013-04-24 14:23:37

  0

Auch dieser Beitrag wird relevant sein, da Ihr Typ gefunden werden muss: http: //st ackoverflow.com/questions/1825147/type-gettypenamespace-ab-classname-returns-null 23 aug. 132013-08-23 20:48:13

+4

Zum Beispiel: ' var driver = (OpenQA.Selenium.IWebDriver) Activator.CreateInstance ("WebDriver", "OpenQA.Selenium.Firefox.FirefoxDriver"). Unwrap(); ' 04 okt. 142014-10-04 04:37:07

+2

Wichtiger Hinweis hier: .Unwrap(), um über das Remoting-Handle zu kommen Sie können die Abgüsse tatsächlich tun. @Endy - Danke 20 jul. 152015-07-20 01:31:38


49

Ich habe diese Methode erfolgreich eingesetzt:

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

Sie werden das zurückgegebene Objekt auf dem gewünschten Objekttyp werfen müssen.

  0

hm .. stellt sich heraus, Benutzernamen sind nicht eindeutig. 21 okt. 082008-10-21 23:48:02

+7

Ich versuche mir ein Szenario vorzustellen, in dem das Erstellen des Objekts über den Klassennamen und das anschließende Umwandeln dieses Typs überhaupt Sinn machen würde. 21 okt. 082008-10-21 23:53:35

+11

Ich sehe was du meinst. Es scheint überflüssig. Wenn Sie den Klassennamen kennen, warum brauchen Sie den dynamischen String? Eine Situation könnte sein, dass Ihr Casting auf eine Basisklasse und die Zeichenfolge Nachkommen dieser Basisklasse darstellt. 21 okt. 082008-10-21 23:58:29

+3

Wenn die Basisklasse bekannt ist, können Sie die Basisklasse oder eine Schnittstelle davon als Argument verwenden, um Nachkommen ohne Reflektion weiterzuleiten. 25 jan. 142014-01-25 09:01:11

+2

Nützliches Szenario: Sie benötigen nur die Serialisierungsschnittstellen oder irgendeine andere ziemlich allgemeine Schnittstelle. Sie werden es nicht in die Klasse werfen, aber zumindest etwas mehr als ein Objekt. 08 dez. 142014-12-08 11:08:49

  0

Xaml beim Klicken auf eine neue Navigationsseite ist das perfekte Beispiel, ich kann mir viele mehr vorstellen. 05 jan. 162016-01-05 19:03:08

+1

Wie man den Cast __von der gegebenen Zeichenfolge__ 25 apr. 162016-04-25 12:00:04


16

Wahrscheinlich sollte meine Frage spezifischer sein. Ich weiß eigentlich eine Basisklasse für die Zeichenfolge so gelöst durch:

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

Die Activator.CreateInstance Klasse verschiedene Methoden hat die gleiche Sache auf verschiedene Weise zu erreichen. Ich hätte es auf ein Objekt anwenden können, aber das oben genannte ist für meine Situation am nützlichsten.

+2

Anstatt im Fragenbereich zu antworten, würde ich vorschlagen, dass Sie Ihre Frage bearbeiten und die Änderungen notieren. Sie werden mehr/bessere Antworten dafür bekommen. 22 okt. 082008-10-22 00:53:45

  0

Vielen Dank, dass Sie die spezifische Codezeile geschrieben haben, die für Sie funktioniert hat. Das Sortieren durch alle Überladungen von CreateInstance und verschiedene Arten, Typen zu erzeugen, hat mir viel Zeit gekostet, die Sie mir erspart haben. 05 jan. 112011-01-05 22:01:12


3

Sie scheinen die Lösung beschrieben zu haben, die Sie implementieren möchten, aber nicht das Problem, das Sie lösen möchten.

Vielleicht versuchen Sie etwas mit Erweiterbarkeit zu tun, in diesem Fall empfehle ich Ihnen, die Managed Extensibility Framework.


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

Warum möchten Sie einen Code wie diesen schreiben? Wenn Sie eine Klasse 'ReportClass' verfügbar haben, können Sie sie direkt wie unten gezeigt instanziieren.

ReportClass report = new ReportClass(); 

Der Code ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass)); verwendet, wenn Sie die erforderliche Klasse verfügbar nicht haben, aber Sie wollen eine Methode dynamisch instanziiert und oder oder aufzurufen.

Ich meine, es ist nützlich, wenn Sie die Baugruppe kennen, aber während Sie den Code schreiben, haben Sie nicht die Klasse verfügbar.


1

Zum Beispiel, wenn Sie Werte verschiedener Typen in einem Datenbankfeld speichern (als String gespeichert) und ein anderes Feld mit dem Typnamen haben (zB String, bool, int, MyClass), dann aus diesen Felddaten könnte denkbarerweise eine Klasse beliebigen Typs unter Verwendung des obigen Codes erstellen und sie mit dem Wert aus dem ersten Feld auffüllen. Dies hängt natürlich vom Typ ab, den Sie speichern, indem Sie eine Methode verwenden, um Strings in den richtigen Typ zu zerlegen. Ich habe dies oft verwendet, um Benutzereinstellungen in einer Datenbank zu speichern.


4

Ich weiß, ich bin zu spät zum Spiel ... aber die Lösung, die Sie suchen, könnte die Kombination der oben genannten sein, und eine Schnittstelle verwenden, um Ihre Objekte öffentlich zugänglichen Aspekten zu definieren.

Wenn dann alle Klassen, die auf diese Weise generiert werden, diese Schnittstelle implementieren, können Sie einfach als Schnittstellentyp festlegen und mit dem resultierenden Objekt arbeiten.


37

Es ist ziemlich einfach. Angenommen, Ihr Klassenname lautet Car, und der Namespace lautet Vehicles. Übergeben Sie den Parameter als Vehicles.Car, der das Objekt vom Typ Car zurückgibt. So können Sie jede Instanz einer beliebigen Klasse dynamisch erstellen.

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

Wenn Ihr Fully Qualified Name (dh Vehicles.Car in diesem Fall) in einer anderen Baugruppe ist, wird die Type.GetType null sein. In solchen Fällen durchlaufen Sie alle Baugruppen und finden die Type. Dazu können Sie den folgenden Code

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; 
} 

Jetzt verwenden, wenn Sie einen parametrisierte Konstruktor gehen Sie wie folgt

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

statt

Activator.CreateInstance(t); 
  0

Wie man es benutzt, ohne zu werfen und wie man den Wurf __ von der gegebenen Schnur __ ?? 25 apr. 162016-04-25 12:16:06

  0

@TaW - Um eine Klasseninstanz verwenden zu können, müssen Sie etwas darüber wissen, was es tun wird - andernfalls können Sie es nicht verwenden. Der gebräuchlichste Anwendungsfall hierfür wäre das Übergeben an eine Schnittstelle, die Ihnen einen vordefinierten Vertrag liefert. (Dies gilt, es sei denn, Sie verwenden 'dynamischen' Code - siehe http://stackoverflow.com/a/2690661/904521) 25 mai. 162016-05-25 08:47:28