¿Cómo puedo crear una instancia de una clase con su nombre de cadena?


Tengo una clase abstracta y quiero iniciar a una clase que extiende.

Tengo el nombre de las clases secundarias como una cadena.

Además de esto...

String childClassString;
MyAbstractClass myObject;

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

¿Cómo puedo hacer esto? Básicamente, ¿cómo me deshago de las declaraciones if aquí?

Author: Robert Harvey, 2010-02-11

3 answers

Mira el Activador.CreateInstance().

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

O

var type = Type.GetType("MyFullyQualifiedTypeName");
var myObject = (MyAbstractClass)Activator.CreateInstance(type);
 99
Author: Seth Petry-Johnson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-11 20:47:57

Creo que esto debería funcionar:

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

El null en el primer parámetro por defecto es el ensamblado de ejecución actual. Para más información: MSDN

Editar: olvidé lanzar a MyAbstractClass

 19
Author: IAbstract,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-02-11 20:53:20

Tuve algunas dificultades para implementar algunas de las respuestas aquí porque estaba tratando de instanciar un objeto de un ensamblaje diferente (pero en la misma solución). Así que pensé en publicar lo que encontré para que funcionara.

Primero, el método Activator.CreateInstance tiene varias sobrecargas. Si solo llamas a Activator.CreateInstance(Type.GetType("MyObj")), eso supone que el objeto está definido en el ensamblado actual, y devuelve un MyObj.

Si lo llamas como se recomienda en las respuestas aquí: Activator.CreateInstance(string AssemblyName, string FullyQualifiedObjectName), entonces en su lugar devuelve un ObjectHandle, y necesita llamar a Unwrap() para obtener su objeto. Esta sobrecarga es útil cuando se intenta llamar a un método definido en un ensamblado diferente (por cierto, puede usar esta sobrecarga en el ensamblado actual, simplemente deje el parámetro AssemblyName null).

Ahora, encontré que la sugerencia anterior de usar typeof(ParentNamespace.ChildNamespace.MyObject).AssemblyQualifiedName para AssemblyName en realidad me dio errores, y no pude hacer que funcionara. Obtendría System.IO.FileLoadException (no se pudo cargar el archivo o el ensamblaje...).

Lo que hice para trabajar es lo siguiente: {[12]]}

var container = Activator.CreateInstance(@"AssemblyName",@"ParentNamespace.ChildNamespace.MyObject");
MyObject obj = (MyObject)container.Unwrap();
obj.DoStuff();
 2
Author: Kevin Fichter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-02 22:58:20