Crear una instancia de una clase a partir de una cadena


168

¿Hay alguna manera de crear una instancia de una clase basada en el hecho de que sé el nombre de la clase en tiempo de ejecución? Básicamente, tendría el nombre de la clase en una cadena.

137

Eche un vistazo al método Activator.CreateInstance.

+14

Relacionado con grandes ejemplos: http : //stackoverflow.com/questions/493490/converting-a-string-to-a-class-name 24 abr. 132013-04-24 14:23:37

  0

También esta publicación será relevante también, ya que debe buscar su tipo: http: // st ackoverflow.com/questions/1825147/type-gettypenamespace-ab-classname-returns-null 23 ago. 132013-08-23 20:48:13

+4

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

+2

Nota importante aquí: .Unwrap() para pasar el control remoto tan puedes hacer los moldes @Endy - Gracias 20 jul. 152015-07-20 01:31:38


49

He utilizado este método con éxito:

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

Tendrá que convertir el objeto devuelto a su tipo de objeto deseado.

  0

hm .. resulta que los nombres de usuario no son únicos. 21 oct. 082008-10-21 23:48:02

+7

Estoy tratando de imaginar un escenario donde crear el objeto a través del nombre de clase y luego lanzarlo como ese tipo tendría algún sentido. 21 oct. 082008-10-21 23:53:35

+11

Veo a qué te refieres. Parece redundante. Si conoce el nombre de la clase, ¿por qué necesita la cadena dinámica? Una situación podría ser que su conversión a una clase base y la cadena representa descendientes de esa clase base. 21 oct. 082008-10-21 23:58:29

+3

Si se conoce la clase base, puede usar la clase base o una interfaz de la misma como argumento para pasar descendientes sin reflexión. 25 ene. 142014-01-25 09:01:11

+2

Escenario útil: solo necesita las interfaces de serialización o cualquier otra interfaz bastante común. No lo lanzarás a la clase, pero al menos a algo más que un objeto 08 dic. 142014-12-08 11:08:49

  0

Xaml al hacer clic en una nueva página de navegación es el ejemplo perfecto, puedo pensar en muchos más. 05 ene. 162016-01-05 19:03:08

+1

¿Cómo hacer el yeso __de la cadena dada__? 25 abr. 162016-04-25 12:00:04


16

Probablemente mi pregunta debería haber sido más específica. Sé realmente una clase base para la cadena por lo resolvió por:

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

La clase Activator.CreateInstance tiene varios métodos para lograr lo mismo de diferentes maneras. Podría haberlo lanzado a un objeto, pero lo anterior es de lo más útil para mi situación.

+2

En lugar de responder en la sección de preguntas, le sugiero que edite su pregunta y observe los cambios. Obtendrá más/mejores respuestas para hacerlo. 22 oct. 082008-10-22 00:53:45

  0

Gracias por publicar la línea específica de código que funcionó para usted. Clasificar a través de todas las sobrecargas de CreateInstance y diferentes formas de generar Types me estaba llevando mucho tiempo, lo cual me salvó. 05 ene. 112011-01-05 22:01:12


3

Parece que ha descrito la solución que desea implementar, pero no el problema que está tratando de resolver.

Quizás esté tratando de hacer algo con la extensibilidad, en cuyo caso le sugiero que consulte el Managed Extensibility Framework.


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

¿por qué quieres escribir un código como este? Si tiene una clase 'ReportClass' disponible, puede crear una instancia directamente como se muestra a continuación.

ReportClass report = new ReportClass(); 

El código ReportClass report = (ReportClass)Activator.CreateInstance(Type.GetType(reportClass)); se utiliza cuando usted no tiene la clase necesaria disponible, pero que desea crear una instancia y o o invocar un método de forma dinámica.

Quiero decir que es útil cuando conoces el conjunto pero al escribir el código no tienes la clase ReportClass disponible.


1

Por ejemplo, si almacena valores de varios tipos en un campo de base de datos (almacenado como cadena) y tiene otro campo con el nombre de tipo (es decir, String, bool, int, MyClass), de esos datos de campo, podría, concebiblemente, crear una clase de cualquier tipo usando el código anterior, y poblarlo con el valor del primer campo. Esto, por supuesto, depende del tipo que está almacenando con un método para analizar las cadenas en el tipo correcto. Lo he usado muchas veces para almacenar configuraciones de preferencias de usuario en una base de datos.


4

Sé que llego tarde al juego ... pero la solución que está buscando podría ser la combinación de lo anterior y el uso de una interfaz para definir los objetos a los que se puede acceder públicamente.

Entonces, si todas sus clases que se generarían de esta manera implementan esa interfaz, puede simplemente convertir como el tipo de interfaz y trabajar con el objeto resultante.


37

Es bastante simple. Suponga que su nombre de clase es Car y el espacio de nombres es Vehicles, luego pase el parámetro como Vehicles.Car que devuelve el objeto de tipo Car. De esta manera, puedes crear cualquier instancia de cualquier clase dinámicamente.

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

Si su Fully Qualified Name (es decir, Vehicles.Car en este caso) es en otro montaje, el Type.GetType será nulo. En tales casos, tiene un ciclo en todos los ensamblajes y encuentra el Type. Para que se puede usar el siguiente código

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

Ahora bien, si desea llamar a un constructor con parámetros hacer lo siguiente

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

en lugar de

Activator.CreateInstance(t); 
  0

¿Cómo usarlo sin emitir y cómo hacer el reparto __de la cadena dada__? 25 abr. 162016-04-25 12:16:06

  0

@TaW: para usar una instancia de clase, necesitará tener un conocimiento de lo que va a hacer; de lo contrario, no podrá usarla. El caso de uso más común para esto sería enviar contenido a alguna interfaz que le da un contrato predefinido. (Esto se mantiene a menos que esté usando el código 'dinámico' - vea http://stackoverflow.com/a/2690661/904521) 25 may. 162016-05-25 08:47:28