Type.GetType ("namespace.abClassName") devuelve nulo

216

Este código:

Type.GetType("namespace.a.b.ClassName")

vuelve null.

y tengo en los usos:

using namespace.a.b;

Actualizar:

El tipo existe, está en una biblioteca de clase diferente y necesito obtenerlo por nombre de cadena.

Omu
fuente
Consulte este stackoverflow.com/questions/441680/… para obtener información sobre cómo obtener el nombre calificado del ensamblaje.
Polyfun

Respuestas:

244

Type.GetType("namespace.qualified.TypeName") solo funciona cuando el tipo se encuentra en mscorlib.dll o en el ensamblado que se está ejecutando actualmente.

Si ninguna de esas cosas es cierta, necesitará un nombre calificado como ensamblado :

Type.GetType("namespace.qualified.TypeName, Assembly.Name")
DrPizza
fuente
3
el tipo existe, está en una biblioteca de clase diferente, y necesito obtenerlo por nombre de cadena
Omu
25
En lugar de usar un nombre calificado como ensamblado, puede cargar el ensamblado por nombre Assembly a = Assembly.Load("SomeLibrary");- y luego cargar el tipo por nombre desde el ensamblaje - Type t = a.GetType("namespace.a.b.ClassName");.
Kenny Evitt
66
Tal vez podría gustaría typeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);puede ahorrar algo de molestia, con el tiempo
Felype
La respuesta de Felype fue la única que pude poner a trabajar.
Rudy Scoggins
Agregue .FirstOrDefault () al comentario de @Felype
Leandro
173

También puede obtener el tipo sin nombre calificado de ensamblado pero con el nombre dll también, por ejemplo:

Type myClassType = Type.GetType("TypeName,DllName");

Tuve la misma situación y funcionó para mí. Necesitaba un objeto de tipo "DataModel.QueueObject" y tenía una referencia a "DataModel", así que obtuve el tipo de la siguiente manera:

Type type = Type.GetType("DataModel.QueueObject,DataModel");

La segunda cadena después de la coma es el nombre de referencia (nombre dll).

Asaf Pala
fuente
2
¿Es este un 'truco' o un método real? No puedo encontrar esto en la documentación -_-. Por cierto, ¡termina mi sufrimiento de 1 semana! gracias
DnR
1
Esta es una solución mucho más limpia, me encantaría ver si hay algún inconveniente debido a esto.
cosaco
44
El formulario utilizado en esta respuesta también es un nombre de tipo totalmente calificado según la gramática de MSDN (por lo que no es un truco ). El formulario es NamespaceTypeName, AssemblyNameSpecdonde AssemblyNameSpecestá el identificador del ensamblaje sin ninguna propiedad. Aunque esta respuesta es esencialmente la misma que la aceptada, supongo que algunas personas prefieren esto porque elimina parte del "ruido" que introducen las propiedades del ensamblaje (por ejemplo Version, Culture PublicKeyToken). Afortunadamente, las propiedades son opcionales .
Martin Liversage
Para los tipos anidados, es posible que deba hacer algo comoAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo
Gracias, funciona para la carpeta App_Code. Ejemplo: Type.GetType ("TypeName, App_Code");
Burak Koray Balcı
79

intenta usar este método

 public static Type GetType(string typeName)
        {
            var type = Type.GetType(typeName);
            if (type != null) return type;
            foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = a.GetType(typeName);
                if (type != null)
                    return type;
            }
            return null ;
        }
hombrecito
fuente
Esto es lo que realmente funcionó para mí. Sin embargo, tuve que ajustar agregando un recorte de subcadena antes del bucle foreach, porque pasé un nombre calificado de ensamblado, y Assembly.GetType () solo funciona si excluye la información del ensamblaje.
Colin
esto se ve genial, pero ¿qué pasa con los genéricos que usan otros tipos de ensamblaje?
Demetris Leptos
No funciona para UWP porque AppDomainno es compatible. No estoy seguro de ninguna alternativa.
James M
25
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
    lock (typeCache) {
        if (!typeCache.TryGetValue(typeName, out t)) {
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
                t = a.GetType(typeName);
                if (t != null)
                    break;
            }
            typeCache[typeName] = t; // perhaps null
        }
    }
    return t != null;
}
erikkallen
fuente
1
esto se ve genial, pero ¿qué pasa con los genéricos que usan otros tipos de ensamblaje?
Demetris Leptos
1
@DemetrisLeptos (Sé que el comentario es antiguo, pero otras personas aún pueden estar interesadas): use int index = typeName.IndexOf ('' '); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } Tenga en cuenta que la Tdel tipo genérico se elimina.
Bernhard Hiller el
25

Si el ensamblaje es parte de la compilación de una aplicación ASP.NET, puede usar la clase BuildManager:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);
LarryBud
fuente
1
Esta es una respuesta fantástica y debería estar más arriba en la página. Funciona a las mil maravillas y es muy simple en comparación con la antigua forma de obtener el nombre de tipo calificado del ensamblado.
Graham
Esto es increíblemente simple y perfecto, ¿me pueden ayudar con la optimización del rendimiento de los objetos de reflexión?
Alok
15

Si su clase no se encuentra en el asalto actual, debe dar nombre calificado y este código muestra cómo obtener el nombre calificado de la clase

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

y luego puede obtener el tipo con qualifiedName

Type elementType = Type.GetType(qualifiedName);
Numan KIZILIRMAK
fuente
8

Si es un tipo anidado, es posible que se olvide de transformar a. a un +

De todos modos, typeof( T).FullNamete diré lo que deberías decir

EDITAR: Por cierto, los usos (como estoy seguro de que sabe) son solo directivas para el compilador en el momento de la compilación y, por lo tanto, no pueden tener ningún impacto en el éxito de la llamada API. (Si tuviera referencias de proyectos o ensamblajes, eso podría haber tenido influencia; por lo tanto, la información no es inútil, solo requiere un poco de filtrado ...)

Ruben Bartelink
fuente
¡Oh mi! ¿Sabes dónde se explica esta sintaxis "+"?
Protector uno
1
Protectorone Lo aprendí de amazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC, pero está un poco anticuado. ¿Puedo recomendar amazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/… como un libro infaliblemente útil para todos los desarrolladores de .NET + que incluye esto? La conclusión es que para los Tipos, el CLR solo tiene el espacio de nombres y el nombre; un tipo anidado no es directamente direccionable. Por lo tanto, un lenguaje, si tiene un concepto de tipo anidado, puede hacer lo que necesita (aunque en general la mayoría de los langs usan un +separador)
Ruben Bartelink
6

Estoy abriendo controles de usuario dependiendo de a qué controles de usuario tenga acceso el usuario especificado en una base de datos. Así que usé este método para obtener el TypeName ...

Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))

Entonces, ahora se puede usar el valor devuelto en strType para crear una instancia de ese objeto.

Stephan
fuente
reabrir un tema épico antiguo ... felicidades. Sin embargo, tengo que rechazar su respuesta porque el TO realmente conoce el Typename y quiere obtener el tipo de él. Por cierto: a qué método hace referencia por <c> GetType (Namespace.ClassName) </c>, si es Type.GetType solo funcionará en los tipos que están dentro de su ensamblaje actual de ejecución o mscorlib, pero como TO no dice de estas condiciones se aplica.
HimBromBeere
2
@HimBromBeere Gracias por el voto negativo. Son las personas como usted las que me desmotivan para publicar mis hallazgos. Todavía estoy aprendiendo el desarrollo y solo estoy tratando de ayudar a otros. ¿Y ahora esperas que responda tu pregunta? Por cierto, he respondido la pregunta correctamente. La clase de la que estaba creando una instancia reside en un proyecto diferente y uno tiene que usar un nombre de ensamblado calificado por eso. Así que por favor lea el resto de los comentarios antes de votar. "el tipo existe, está en una biblioteca de clase diferente, y necesito obtenerlo por nombre de cadena - Omu"
Stephan
6

Cuando solo tengo el nombre de la clase, uso esto:

Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();
Marchino
fuente
5

Como Type.GetType (String) necesita el Type.AssemblyQualifiedName , debe usar Assembly.CreateQualifiedName (String, String) .

string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);

La Versión, Cultura y PublicKeyToken no son necesarias, por assemblyNameeso puede usar MyAssembly.GetName (). Name.

Acerca de Type.GetType (String) :

Si el tipo está en el ensamblaje que se está ejecutando actualmente o en Mscorlib.dll, es suficiente proporcionar el nombre de tipo calificado por su espacio de nombres.

Florian Talour
fuente
4

Si se hace referencia al ensamblaje y la clase es visible:

typeof(namespace.a.b.ClassName)

GetType devuelve nulo porque no se encuentra el tipo, con typeof, el compilador puede ayudarlo a descubrir el error.

Guillaume
fuente
el tipo existe, está en una biblioteca de clase diferente, y necesito obtenerlo por nombre de cadena
Omu
4

Intente usar el nombre de tipo completo que incluye la información del ensamblaje, por ejemplo:

string typeName = @"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);

Tuve la misma situación cuando estaba usando solo el namesspace.classname para obtener el tipo de una clase en un ensamblado diferente y no funcionaría. Solo funcionó cuando incluí la información de ensamblaje en mi cadena de tipo como se muestra arriba.

Ismail Hawayel
fuente
3

Asegúrese de que la coma va directamente después del nombre completo

typeof(namespace.a.b.ClassName, AssemblyName)

Como esto no funcionará

typeof(namespace.a.b.ClassName ,AssemblyName)

Estuve perplejo por unos días en este

jack_tux
fuente
2

¡Para mí, un "+" fue la clave! Esta es mi clase (es anidada):

namespace PortalServices
{
public class PortalManagement : WebService
{
    public class Merchant
    {}
}
}

y esta línea de código funcionó:

Type type = Type.GetType("PortalServices.PortalManagement+Merchant");
Arash Masir
fuente
1

Esta solución anterior parece ser la mejor para mí, pero no funcionó para mí, así que lo hice de la siguiente manera:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);

Type myType = Type.GetType(typeAssemblyQualifiedName);

La condición previa es que conozca el camino de la asamblea. En mi caso, lo sé porque este es un ensamblaje construido a partir de otro proyecto interno y está incluido en la carpeta bin de nuestro proyecto.

En caso de que sea importante, estoy usando Visual Studio 2013, mi objetivo .NET es 4.0. Este es un proyecto ASP.NET, por lo que obtengo una ruta absoluta a través de HttpContext. Sin embargo, la ruta absoluta no es un requisito como parece de MSDN en AssemblyQualifiedNames

Ozair Kafray
fuente
0

Hice trampa. Dado que los tipos que quiero crear (por nombre) están todos en un dll que controlo, solo pongo un método estático en el dll en el ensamblado que toma un nombre simple y llama a type.GetType desde ese contexto y devuelve el resultado .

El propósito original era que el tipo pudiera especificarse por nombre en los datos de configuración. Desde entonces he cambiado el código para que el usuario especifique un formato para procesar. Las clases de controlador de formato implementan una interfaz que determina si el tipo puede analizar el formato especificado. Luego uso la reflexión para buscar tipos que implementen la interfaz y encontrar uno que maneje el formato. Entonces, la configuración especifica un nombre de formato, un tipo no específico. El código de reflexión puede mirar dlls adyacentes y cargarlos, así que tengo una arquitectura de plug-in de tipo pobre.

Darrel Lee
fuente
Hola, he votado por error, edita tu respuesta para poder deshacerla.
coloboxp