2009-04-06 8 views

Respuesta

90

El format for generics es el nombre, un carácter `, el número de parámetros de tipo, seguidos de una lista delimitada por comas de los tipos entre paréntesis:

Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]"); 

No estoy seguro de que haya una manera fácil de convertir la sintaxis de C# para los genéricos al tipo de cadena que quiere el CLR. Empecé a escribir una expresión regular rápida para analizarla como mencionaste en la pregunta, pero me di cuenta de que a menos que abandones la capacidad de tener genéricos anidados como parámetros de tipo, el análisis se volverá muy complicado.

+0

+1 - ¡excelente respuesta, gracias! ¡Estaba jugueteando tratando de descubrir cómo manejar los genéricos! –

+0

Gracias. Esto funciona y tengo que modificar el código para formatear la cadena de esta manera. Sin embargo, me preguntaba si todavía hay una manera de usar simplemente: "MyClass " exactamente como se muestra en la cadena para obtener la instancia de Type. Se ve mucho más limpio. – DeeStackOverflow

+0

No tiene que modificar el código para formatear la cadena de esta manera, simplemente llame a ToString() en el Tipo. –

38

Salida Activator.CreateInstance - se le puede llamar con un tipo

Activator.CreateInstance(typeof(MyType)) 

o con un nombre de ensamblado y tipo que string

Activator.CreateInstance("myAssembly", "myType") 

Esto le dará una instancia del tipo que necesita.

Si necesita el Type en lugar de la instancia, utilice el método Type.GetType() y el nombre completo del tipo que le interesa, por ejemplo:

string s = "System.Text.StringBuilder"; 
Type myClassType = Type.GetType(s); 

que usted va a dar al Type en cuestión .

+2

Esto se pone una instancia de la clase, no una instancia System.Type, que basa en el fragmento de código, parece ser lo que OP está buscando. –

0

No tengo mucho tiempo para analizar todo esto, aunque creo que he visto algunas respuestas similares. En particular, creo que están haciendo exactamente lo que quiere hacer aquí:

Entity Framework Generic Repository Error

(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>(); 

Esperemos que esto ayude, que me haga saber más específicamente si esto no es así.

3

para obtener sólo el objeto de texto de la cadena, utilice:

Type mytype = Type.GetType(typeName); 

entonces puede pasar esto a Activator.CreateInstance():

Activator.CreateInstance(mytype); 
26

He necesitado algo así y terminé escribiendo un código para analizar los nombres de tipos simples que necesitaba. Por supuesto, hay margen de mejora, ya que no identificará nombres de tipos genéricos como List<string>, pero se aplica perfectamente a string, int[], decimal? y demás. Compartir en caso de que esto ayude a alguien.

public static class TypeExtensions 
{ 
    public static Type GetTypeFromSimpleName(string typeName) 
    { 
    if (typeName == null) 
     throw new ArgumentNullException("typeName"); 

    bool isArray = false, isNullable = false; 

    if (typeName.IndexOf("[]") != -1) 
    { 
     isArray = true; 
     typeName = typeName.Remove(typeName.IndexOf("[]"), 2); 
    } 

    if (typeName.IndexOf("?") != -1) 
    { 
     isNullable = true; 
     typeName = typeName.Remove(typeName.IndexOf("?"), 1); 
    } 

    typeName = typeName.ToLower(); 

    string parsedTypeName = null; 
    switch (typeName) 
    { 
     case "bool": 
     case "boolean": 
     parsedTypeName = "System.Boolean"; 
     break; 
     case "byte": 
     parsedTypeName = "System.Byte"; 
     break; 
     case "char": 
     parsedTypeName = "System.Char"; 
     break; 
     case "datetime": 
     parsedTypeName = "System.DateTime"; 
     break; 
     case "datetimeoffset": 
     parsedTypeName = "System.DateTimeOffset"; 
     break; 
     case "decimal": 
     parsedTypeName = "System.Decimal"; 
     break; 
     case "double": 
     parsedTypeName = "System.Double"; 
     break; 
     case "float": 
     parsedTypeName = "System.Single"; 
     break; 
     case "int16": 
     case "short": 
     parsedTypeName = "System.Int16"; 
     break; 
     case "int32": 
     case "int": 
     parsedTypeName = "System.Int32"; 
     break; 
     case "int64": 
     case "long": 
     parsedTypeName = "System.Int64"; 
     break; 
     case "object": 
     parsedTypeName = "System.Object"; 
     break; 
     case "sbyte": 
     parsedTypeName = "System.SByte"; 
     break; 
     case "string": 
     parsedTypeName = "System.String"; 
     break; 
     case "timespan": 
     parsedTypeName = "System.TimeSpan"; 
     break; 
     case "uint16": 
     case "ushort": 
     parsedTypeName = "System.UInt16"; 
     break; 
     case "uint32": 
     case "uint": 
     parsedTypeName = "System.UInt32"; 
     break; 
     case "uint64": 
     case "ulong": 
     parsedTypeName = "System.UInt64"; 
     break; 
    } 

    if (parsedTypeName != null) 
    { 
     if (isArray) 
     parsedTypeName = parsedTypeName + "[]"; 

     if (isNullable) 
     parsedTypeName = String.Concat("System.Nullable`1[", parsedTypeName, "]"); 
    } 
    else 
     parsedTypeName = typeName; 

    // Expected to throw an exception in case the type has not been recognized. 
    return Type.GetType(parsedTypeName); 
    } 
} 

Su uso es tan simple como escribir esto:

Type t; 

t = TypeExtensions.GetTypeFromSimpleName("string"); 
t = TypeExtensions.GetTypeFromSimpleName("int[]"); 
t = TypeExtensions.GetTypeFromSimpleName("decimal?"); 
+5

Este es un fragmento de código increíblemente útil. –

+1

Corto, perfecto, ¡extremadamente útil! Gracias – xrnd

Cuestiones relacionadas