2012-06-19 35 views
106

Si recibo una cadena que contiene el nombre de una clase (objeto) y quiero convertir esta cadena a un tipo real (el de la cadena), ¿cómo puedo hacer esto?Convertir cadena a tipo C#

me trataron

Type.GetType("System.Int32") 

por ejemplo, que parece funcionar.

Pero cuando trato con mi propio objeto, siempre devuelve un valor nulo ...

que no tienen idea de lo que será en la cadena de antemano por lo que es mi única fuente para convertirlo en su tipo real.

Type.GetType("NameSpace.MyClasse"); 

¿Alguna idea?

+1

muéstranos tu ejemplo de código falló, también nos muestran lo que es el tipo de original. –

+0

Además, cuéntanos por qué/qué estás tratando de hacer. Puede haber una solución alternativa que no requiera que envíe una representación de cadena del tipo. – Trisped

Respuesta

241

Solo puede usar solo el nombre del tipo (con su espacio de nombre, por supuesto) si el tipo está en mscorlib o el conjunto que realiza la llamada. De lo contrario, usted tiene que incluir el nombre del ensamblado así:

Type type = Type.GetType("Namespace.MyClass, MyAssembly"); 

Si el conjunto tiene un nombre, que tiene que incluir toda esa información también. Consulte la documentación para Type.GetType(string) para obtener más información.

Alternativamente, si tiene una referencia al ensamblado ya (por ejemplo, a través de un tipo bien conocido), puede utilizar Assembly.GetType:

Assembly asm = typeof(SomeKnownType).Assembly; 
Type type = asm.GetType(namespaceQualifiedTypeName); 
+4

Jon, como dijiste una vez, es una lástima cuando no recibes votos por votos porque eres un usuario importante. Cierto. También es una lástima cuando no se reciben votaciones porque un usuario superior también ha respondido la pregunta. Especialmente es una lástima cuando no recibes votaciones porque Jon Skeet también ha respondido a la pregunta :) – abatishchev

+4

@abatishchev Dudo que esté obteniendo muchos votos sobre ti solo porque es un usuario importante.Su respuesta fue ligeramente posterior (por lo que menos personas lo leerán ya que no pasarán de la primera respuesta correcta), su publicación incluyó más información y su publicación respondió a la pregunta original (consulte el comentario de Jon en su publicación original). Pensé en votar por Jon, pero no lo hice porque su publicación no fue fácil de leer. No pensé en votarte el tuyo, ya que básicamente reformulaste la operación sin responder el problema. En resumen, no culpe a la presencia de un usuario superior por su falta de votos. – Trisped

+0

Funciona bien ... el único problema que tengo ahora es cuando tengo System.Collections.List o IList. Cómo puedo hacer eso ? Porque no solo quiero el tipo de lista, sino el tipo que contiene la lista. Me gusta la lista por ejemplo. Y recuerda que no sé de antemano lo que habrá en la cuerda, solo tengo que lanzar un Type real. Es posible ? – Vinhent

23

Probar:

Type type = Type.GetType(inputString); //target type 
object o = Activator.CreateInstance(type); // an instance of target type 
YourType your = (YourType)o; 

Jon Skeet es correcto como por lo general :)

Actualización: Puede especificar el ensamblaje que contiene el tipo de destino de varias maneras, como mencionó Jon, o:

YourType your = (YourType)Activator.CreateInstance("AssemblyName", "NameSpace.MyClass"); 
+6

El punto es que Type.GetType está devolviendo nulo para el OP. Vea mi respuesta para la causa más probable. –

+1

Funciona bien ... el único problema que tengo ahora es cuando tengo System.Collections.List o IList. Cómo puedo hacer eso ? Porque no solo quiero el tipo de lista, sino el tipo que contiene la lista. Me gusta la lista por ejemplo. Y recuerda que no sé de antemano lo que habrá en la cuerda, solo tengo que lanzar un Type real. Es posible ? – Vinhent

+0

Puede que desee tener en cuenta que 'inputString' debe ser espacio de nombre completo, ya que eso es lo que me atraviesa al comparar el suyo con el suyo. –

9

Si usted realmente desea conseguir el tipo de nombre que puede utilizar el siguiente:

System.AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).First(x => x.Name == "theassembly"); 

Tenga en cuenta que puede mejorar el rendimiento de este drásticamente cuanto más información que tenga sobre el tipo que' Estoy tratando de cargar.

+0

Funciona bien ... el único problema que tengo ahora es cuando tengo System.Collections.List o IList. Cómo puedo hacer eso ? Porque no solo quiero el tipo de lista, sino el tipo que contiene la lista. Me gusta la lista por ejemplo. Y recuerda que no sé de antemano lo que habrá en la cuerda, solo tengo que lanzar un Type real. Es posible ? – Vinhent

+0

¡Muy agradable y fácil de trabajar con la respuesta! +1 – Karamafrooz

3

uso del método siguiente LOADTYPE utilizar System.Reflection para cargar todos los registrados (GAC) y referenciados asambleas y compruebe typeName

public Type[] LoadType(string typeName) 
{ 
    return LoadType(typeName, true); 
} 

public Type[] LoadType(string typeName, bool referenced) 
{ 
    return LoadType(typeName, referenced, true); 
} 

private Type[] LoadType(string typeName, bool referenced, bool gac) 
{ 
    //check for problematic work 
    if (string.IsNullOrEmpty(typeName) || !referenced && !gac) 
     return new Type[] { }; 

    Assembly currentAssembly = Assembly.GetExecutingAssembly(); 

    List<string> assemblyFullnames = new List<string>(); 
    List<Type> types = new List<Type>(); 

    if (referenced) 
    {   //Check refrenced assemblies 
     foreach (AssemblyName assemblyName in currentAssembly.GetReferencedAssemblies()) 
     { 
      //Load method resolve refrenced loaded assembly 
      Assembly assembly = Assembly.Load(assemblyName.FullName); 

      //Check if type is exists in assembly 
      var type = assembly.GetType(typeName, false, true); 

      if (type != null && !assemblyFullnames.Contains(assembly.FullName)) 
      { 
       types.Add(type); 
       assemblyFullnames.Add(assembly.FullName); 
      } 
     } 
    } 

    if (gac) 
    { 
     //GAC files 
     string gacPath = Environment.GetFolderPath(System.Environment.SpecialFolder.Windows) + "\\assembly"; 
     var files = GetGlobalAssemblyCacheFiles(gacPath); 
     foreach (string file in files) 
     { 
      try 
      { 
       //reflection only 
       Assembly assembly = Assembly.ReflectionOnlyLoadFrom(file); 

       //Check if type is exists in assembly 
       var type = assembly.GetType(typeName, false, true); 

       if (type != null && !assemblyFullnames.Contains(assembly.FullName)) 
       { 
        types.Add(type); 
        assemblyFullnames.Add(assembly.FullName); 
       } 
      } 
      catch 
      { 
       //your custom handling 
      } 
     } 
    } 

    return types.ToArray(); 
} 

public static string[] GetGlobalAssemblyCacheFiles(string path) 
{ 
    List<string> files = new List<string>(); 

    DirectoryInfo di = new DirectoryInfo(path); 

    foreach (FileInfo fi in di.GetFiles("*.dll")) 
    { 
     files.Add(fi.FullName); 
    } 

    foreach (DirectoryInfo diChild in di.GetDirectories()) 
    { 
     var files2 = GetGlobalAssemblyCacheFiles(diChild.FullName); 
     files.AddRange(files2); 
    } 

    return files.ToArray(); 
}