Cómo: Generar tipos genéricos dinámicos
Hace un tiempo, empecé a preguntarme: “Cómo podría crear objetos genéricos específicos como List o Dictionary con tipos enviados como parámetros?”. Todos sabemos que entre “” tenemos que especificar el(los) tipo(s), pero ciertamente no podemos hacer algo como “Dictionary”.
Mi estimado colega Angel “Java” Lopez me dijo una vez que dicha creación dinámica de genéricos se podía hacer (no de esa forma, se refería a que el objetivo se podía alcanzar :P). Así que comencé a investigar y preguntar, hasta que encontré el método Type.MakeGenericType(Type[] args). Leí la documentación y finalmente hice funcionar la idea! Así que lo compartiré con ustedes!
Código Ejemplo
Este ejemplo muestra una clase llamada FabricaDeGenericos que genera objetos genéricos de acuerdo con los tipos pasados como parámetros. Para este propósito, la clase expone un método llamado CrearInstanciaGenerica(Type tipoBase, Type[] tiposDeArgumento).
Parámetros:
- tipoBase: el tipo que será el tipo base genérico, y
- tiposDeArgumento: un arreglo (array) de argumentos que proveerá los tipos para los argumentos genéricos.
Devuelve:
- object.
public class FabricaDeGenericos
{
public object CrearInstanciaGenerica(
Type tipoBase, Type[] tiposDeArgumento
)
{
return Activator.CreateInstance(tipoBase.MakeGenericType(
tiposDeArgumento));
}
}
Esta clase recibe el tipo de la clase base del genérico y sus argumentos genéricos, y luego llama al método MakeGenericType(Type[] args) de la clase System.Type de tipoBase que construye el genérico.
Hora, podemos preparar nuestra clase Cliente (aquí es una Windows Console Application) para que use la clase FabricaDeGenericos de la siguiente manera:
class Program
{
static void Main(string[] args)
{
FabricaDeGenericos miFabricaDeGenericos = new FabricaDeGenericos();
Type[] misTiposDeArgumento = { typeof(string), typeof(object) };
Dictionary<string, object> miDiccionario =
(Dictionary<string, object>)miFabricaDeGenericos.CrearInstanciaGenerica(
typeof(Dictionary), misTiposDeArgumento);
Console.WriteLine(miDiccionario.GetType().FullName);
Console.Read();
}
}
Aquí, estoy creando un nuevo Dictionary. Si le dan una mirada al código del Cliente, le estoy enviando el objeto tipo base que representa el tipo genérico Dictionary omitiendo los argumentos tipo, pero manteniendo la coma que los separa, para que el compilador pueda inferir el número de parámetros tipo (y, por supuesto, para evitar excepciones :P). Luego, también le envío un arreglo (array) de tipos (string para TKey y object para TValue) para reemplazar los parámetros tipo de Dictionary.
NOTA: La conversión (casting) es necesaria ya que el método CrearInstanciaGenerica() devuelve object!
Finalmente, llamo al método MakeGenericType(Type[] args) en el tipoBase el cuál devolverá el tipo para Dictionary. Activator.CreateInstance(Type TType) simplemente genera el objeto que será devuelto de acuerdo con el tipo.
La línea Console.WriteLine() muestra en la consola el tipo construido del nuevo objeto.
Más información:
- Type.MakeGenericType Method.
- Type Clase y Type Miembros.
- Reflexión y tipos genéricos.
- Genéricos en .NET Framework.
- Salu2, Nacho
See this topic in English.