¿Cómo crear dinámicamente un objeto C# genérico usando la reflexión? [duplicar]

Resuelto Jeff asked hace 15 años • 5 respuestas

En C# tengo el siguiente objeto:

public class Item
{ }

public class Task<T>
{ }

public class TaskA<T> : Task<T>
{ }

public class TaskB<T> : Task<T>
{ }

Quiero crear dinámicamente TaskA o TaskB usando la reflexión de C# ( Activator.CreateInstance ). Sin embargo, no sabría el tipo de antemano, por lo que necesito crear dinámicamente la Tarea A basada en una cadena como "namespace.TaskA" o "namespace.TaskAB".

Jeff avatar Jul 20 '09 08:07 Jeff
Aceptado

Consulte este artículo y este sencillo ejemplo . Traducción rápida del mismo para tus clases...

var d1 = typeof(Task<>);
Type[] typeArgs = { typeof(Item) };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);

Según su edición: para ese caso, puede hacer esto...

var d1 = Type.GetType("GenericTest.TaskA`1"); // GenericTest was my namespace, add yours
Type[] typeArgs = { typeof(Item) };
var makeme = d1.MakeGenericType(typeArgs);
object o = Activator.CreateInstance(makeme);

Para ver de dónde se me ocurrió backtick1 para el nombre de la clase genérica, consulte este artículo .

Nota: si su clase genérica acepta múltiples tipos, debe incluir comas cuando omita los nombres de los tipos, por ejemplo:

Type type = typeof(IReadOnlyDictionary<,>);
JP Alioto avatar Jul 20 '2009 02:07 JP Alioto

De hecho, no podrías escribir la última línea.

Pero probablemente no quieras crear el objeto, simplemente por crearlo. Probablemente quieras llamar a algún método en tu instancia recién creada.

Entonces necesitarás algo como una interfaz:

public interface ITask 
{
    void Process(object o);
}

public class Task<T> : ITask
{ 
   void ITask.Process(object o) 
   {
      if(o is T) // Just to be sure, and maybe throw an exception
        Process(o as T);
   }

   public void Process(T o) { }
}

y llámalo con:

Type d1 = Type.GetType("TaskA"); //or "TaskB"
Type[] typeArgs = { typeof(Item) };
Type makeme = d1.MakeGenericType(typeArgs);
ITask task = Activator.CreateInstance(makeme) as ITask;

// This can be Item, or any type derived from Item
task.Process(new Item());

En cualquier caso, no se le enviará estáticamente a un tipo que no conozca de antemano ("hazme" en este caso). ITask le permite llegar a su tipo de objetivo.

Si esto no es lo que desea, probablemente necesitará ser un poco más específico en lo que intenta lograr con esto.

Jérôme Laban avatar Jul 20 '2009 02:07 Jérôme Laban

Me parece que la última línea de su código de ejemplo debería ser simplemente:

Task<Item> itsMe = o as Task<Item>;

¿O me estoy perdiendo algo?

Ben M avatar Jul 20 '2009 02:07 Ben M