¿Cómo crear dinámicamente un objeto C # genérico utilizando la reflexión?

En C # tengo el siguiente objeto:

public class Item { } public class Task { } public class TaskA : Task { } public class TaskB : Task { } 

Quiero crear dinámicamente TaskA o TaskB usando C # reflection ( Activator.CreateInstance ). Sin embargo, no sabría el tipo de antemano, así que necesito crear dinámicamente TaskA basado en una cadena como “namespace.TaskA” o “namespace.TaskAB”.

Mira este artículo y este sencillo ejemplo . Traducción rápida de lo mismo a sus 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 saqué backtick1 para el nombre de la clase genérica, vea este artículo .

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

 Type type = typeof(IReadOnlyDictionary<,>); 

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

Pero probablemente no desee crear el objeto, solo por el bien o crearlo. Probablemente desee llamar a algún método en su instancia recién creada.

Entonces necesitarás algo así como una interfaz:

 public interface ITask { void Process(object o); } public class Task : 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 lo lanzará estáticamente a un tipo que no conozca de antemano (“makeme” en este caso). ITask te permite llegar a tu tipo de objective.

Si esto no es lo que quieres, probablemente necesitarás ser un poco más específico en lo que estás tratando de lograr con esto.

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

 Task itsMe = o as Task; 

¿O me estoy perdiendo algo?

Asegúrese de estar haciendo esto por una buena razón, una función simple como la siguiente permitiría el tipado estático y le permite a su IDE hacer cosas como “Buscar referencias” y Refactorizar -> Cambiar nombre.

 public Task  factory (String name) { Task  result; if (name.CompareTo ("A") == 0) { result = new TaskA (); } else if (name.CompareTo ("B") == 0) { result = new TaskB (); } return result; } 

Sé que esta pregunta está resuelta pero, para el beneficio de cualquier otra persona que la lea; Si tiene todos los tipos involucrados como cadenas, puede hacer esto como un trazador de líneas:

 IYourInterface o = (Activator.CreateInstance(Type.GetType("Namespace.TaskA`1[OtherNamespace.TypeParam]") as IYourInterface); 

Cada vez que he hecho este tipo de cosas, he tenido una interfaz que quería utilizar para el código posterior, por lo que he convertido la instancia creada en una interfaz.

    Intereting Posts