type examples ejemplo assemblies clr types gettype

assemblies - examples - ¿Por qué System.Type.GetType("Xyz") devuelve nulo si existe typeof(Xyz)?



type.gettype( system.string) (4)

Me he encontrado con un comportamiento extraño en mi (enorme) proyecto .NET 4. En algún punto del código, me refiero a un tipo completamente calificado, por ejemplo:

System.Type type = typeof (Foo.Bar.Xyz);

Más tarde, hago esto:

System.Type type = System.Type.GetType ("Foo.Bar.Xyz");

y vuelvo null . No entiendo por qué sucede esto, porque el nombre de mi tipo es correcto, he comprobado con otros tipos y se resuelven correctamente. Además, la siguiente consulta LINQ encuentra el tipo:

var types = from assembly in System.AppDomain.CurrentDomain.GetAssemblies () from assemblyType in assembly.GetTypes () where assemblyType.FullName == typeName select assemblyType; System.Type type = types.FirstOrDefault ();

¿Hay alguna razón por la cual System.Type.GetType podría fallar?

Finalmente tuve que recurrir a este fragmento de código en lugar de GetType :

System.Type MyGetType(string typeName) { System.Type type = System.Type.GetType (typeName); if (type == null) { var types = from assembly in System.AppDomain.CurrentDomain.GetAssemblies () from assemblyType in assembly.GetTypes () where assemblyType.FullName == typeName select assemblyType; type = types.FirstOrDefault (); } return type; }


De la documentación de MSDN (mi énfasis):

Si typeName incluye el espacio de nombres pero no el nombre del ensamblado, este método busca solo el ensamblado del objeto llamante y Mscorlib.dll , en ese orden. Si typeName está completamente calificado con el nombre de conjunto parcial o completo, este método busca en el conjunto especificado. Si el ensamblaje tiene un nombre seguro, se requiere un nombre de ensamblaje completo.


Me topé con un problema similar y quiero dejar esto aquí.

En primer lugar, puede especificar el AssemblyName en la cadena

var type = System.Type.GetType("Foo.Bar.Xyz, Assembly.Name");

Sin embargo, esto solo funciona para ensamblajes sin un nombre fuerte. La explicación ya está en la respuesta de Simons. If the assembly has a strong name, a complete assembly name is required.

Mi problema fue que tuve que resolver un System.Dictionary<?,?> De una cadena en tiempo de ejecución. Para un Dictionary<int, string> esto podría ser fácil, pero ¿qué pasa con un Dictionary<int, Image> ?

esto resultaría en

var typeName = "System.Collections.Generic.Dictionary`2[System.Int32, [System.Drawing.Image, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a]]";

Pero no quiero escribir el nombre fuerte. Especialmente porque no quiero incluir las versiones ya que planeo apuntar múltiples marcos con mi código.

Así que aquí está mi solución

privat statice void Main() { var typeName = "System.Collections.Generic.Dictionary`2[System.Int32, [System.Drawing.Image, System.Drawing]]"; var type = Type.GetType(typeName, ResolveAssembly, ResolveType); } private static Assembly ResolveAssembly(AssemblyName assemblyName) { if (assemblyName.Name.Equals(assemblyName.FullName)) return Assembly.LoadWithPartialName(assemblyName.Name); return Assembly.Load(assemblyName); } private static Type ResolveType(Assembly assembly, string typeName, bool ignoreCase) { return assembly != null ? assembly.GetType(typeName, false, ignoreCase) : Type.GetType(typeName, false, ignoreCase); }

Type.GetType(...) tiene una sobrecarga que acepta una función para el ensamblaje y la resolución de tipos, lo cual es nítido. Assembly.LoadWithPartialName está en desuso pero, si se elimina en el futuro, podría pensar en un reemplazo (iterar todos los ensamblados en el dominio de aplicación actual y comparar los nombres parciales).


Por lo que sé, GetType busca "Xyz" en un ensamblaje llamado Foo.Bar.dll y supongo que no existe.

GetType se basa en el paso de la ruta exacta a Xyz en el ensamblaje. El ensamblado y el espacio de nombres no tienen que estar relacionados.

Pruebe System.Type type = System.Type.GetType(typeof(Foo.Bar.Xyz).AssemblyQualifiedName) y vea si funciona.

La razón por la que lo encuentra con su ejemplo de LINQ es que está utilizando GetAssemblies que obtiene los ensamblados que se han cargado en el contexto de ejecución actual y, por lo tanto, tiene los detalles que necesita para encontrar todos los tipos dentro de los ensamblados.


Si solo da un nombre de clase (que necesita estar completamente calificado en términos del espacio de nombres, por supuesto) Type.GetType(string) solo buscará en el ensamblado que se está ejecutando actualmente y en mscorlib. Si desea obtener tipos de cualquier otro conjunto, debe especificar el nombre absolutamente completo, incluida la información del conjunto. Como dice François, Type.AssemblyQualifiedName es una buena manera de ver esto. Aquí hay un ejemplo:

using System; using System.Windows.Forms; class Test { static void Main() { string name = typeof(Form).AssemblyQualifiedName; Console.WriteLine(name); Type type = Type.GetType(name); Console.WriteLine(type); } }

Salida:

System.Windows.Forms.Form, System.Windows.Forms, Version = 4.0.0.0, Culture = neutral,
PublicKeyToken = b77a5c561934e089
System.Windows.Forms.Form

Tenga en cuenta que si está utilizando un ensamblaje con nombre seguro (como Form en este caso), debe incluir toda la información del ensamblaje: control de versiones, token de clave pública, etc.

Si está utilizando un ensamblaje sin nombre seguro, es más fácil, algo así como:

Foo.Bar.Baz, MyCompany.MyAssembly

para un tipo llamado Baz en el espacio de nombres Foo.Bar , en el ensamblaje MyCompany.MyAssembly . Tenga en cuenta la ausencia de ".dll" al final, eso es parte del nombre del archivo, pero no el nombre del ensamblado.

También debe tener en cuenta las diferencias entre los nombres C # y los nombres CLR para cosas como clases anidadas y genéricos. Por ejemplo, typeof(List<>.Enumerator) tiene un nombre de System.Collections.Generic.List`1+Enumerator[T] . El lado de los genéricos es complicado de resolver, pero el bit de tipo anidado es fácil: solo se representa con un "+" en lugar de con el "". Usted usaría en C #.