Quand Assembly.GetType (name) `renvoie-t-il null?

J’ai un code comme ci-dessous

public static Type ToType(Type sType) { Assembly assembly = Assembly.Load(SerializableType.AssemblyName); type = assembly.GetType(sType.Name); } 

METTRE À JOUR

Dans l’interface utilisateur, si je définit la valeur pour la classe de base, aucun problème ne se produit car leur assemblage crée une manière normale, mais si vous définissez une valeur pour la classe définie par l’utilisateur, leur assemblage crée une manière différente, comme illustré ci-dessous.

Il renvoie la valeur null si le nom de la classe n’est pas trouvé, probablement parce que la propriété Name de votre type renvoie uniquement le nom du type, et non le nom de l’espace de noms pour la qualifier. Assurez-vous que votre propriété Name inclut l’espace de noms le qualifiant également.

Selon le MSDN sur Assembly.GetType (nom de chaîne), il renvoie:

Un object qui représente la classe spécifiée ou Nothing si la classe n’est pas trouvée.

Ainsi, étant donné que vous obtenez une valeur null , le nom du type ne peut pas être trouvé. La raison la plus probable est qu’il est mal orthographié ou que vous n’avez pas ajouté de préfixe au nom de type avec l’espace de noms.

Cette méthode ne recherche que l’instance d’assembly en cours. Le paramètre name inclut l’espace de noms mais pas l’assembly.

Ou bien, il est également possible que la casse soit fausse sur le nom du type. Il existe une version de GetType() qui prend en charge un argument bool pour une comparaison de noms non sensible à la casse.

ps L’espace de noms est nécessaire car le nom de l’assembly peut ne pas être un indicateur de l’espace de noms. Autrement dit, si j’avais un type dans un assembly MySystem.MyClasses.DLL , cela ne signifie pas que le type est nécessairement dans l’espace de noms MySystem.MyClasses .

La page MSDN complète (toujours utile de voir ce qui se passe / se retourne) se trouve ici: Méthode Assembly.GetType (Ssortingng)

Il est évident que l’assembly existe (ou il renverrait null et vous obtiendriez une NullReferenceException ). Par conséquent, une autre possibilité est que vous n’ayez pas la même version de l’assembly que vous attendez (le programme utilisant ce code a une version différente de l’assemblage puis le code générant les données).

Votre type peut être non public. Par défaut, la reflection ne fonctionne que sur les types et les membres publics. Si vous n’augmentez pas votre niveau de sécurité, le type sera nul.

J’ai eu du mal à trouver le nom correctement qualifié d’un type dans une dll que j’essayais d’utiliser, mais j’ai trouvé GetTypes () vraiment utile pour répertorier tous les éléments disponibles. En VB:

  Dim t As Type() = assem.GetTypes() Dim s As Ssortingng = "" For i As Integer = 0 To t.Length - 1 s = s & t(i).FullName & vbCrLf Next i MsgBox(s) 

Voici un exemple réel d’une application UWP. L’espace de nom de l’application est My_App. La classe FooPage se trouve dans le dossier Vues. Le moyen d’obtenir le type est le suivant:

 Type typePage = Assembly.GetExecutingAssembly().GetType("My_App.Views.FooPage}"); 

Si vous n’êtes pas sûr du nom de votre type, utilisez le code suivant pour vider toutes les classes et trouver celle qui vous intéresse:

 foreach(Type t in Assembly.GetExecutingAssembly().GetTypes()) { Debug.WriteLine($"{t.Namespace}.{t.Name}"); } 

Cela ne fonctionne pas simplement parce que vous chargez du code provenant d’un autre assemblage que l’assembly de classe de base. Si vous essayez d’appeler ce code à partir d’un ensemble différent de celui qui contient la définition du type recherché, le type sera résolu en null.

C’est raisonnable, car vous devez fournir un nom de type qualifié d’assembly, c’est-à-dire Type.AssemblyQualifiedName, et pas seulement le nom complet lui-même.

Si vos classes dérivées définies dans un autre assembly que celui de la classe de base avec un exemple de code, votre code de l’assembly où la classe de base est définie ne fonctionnera pas.

Ça va marcher


 public static Type ToType(Type type, ITypeResolver typeResolver) { Assembly assembly = Assembly.Load(SerializableType.AssemblyName); type = typeResolver.GetType(assembly, sType.AssemblyQualifiedName); } 

Vous pouvez utiliser un TypeResolver comme ça (C # 7.2)

 public interface ITypeResolver { ssortingng GetName(Type type); Type GetType(Assembly assembly, ssortingng typeName); } class TypeResolver : ITypeResolver { public ssortingng GetName(Type type) => type.AssemblyQualifiedName; public Type GetType(Assembly assembly, ssortingng typeName) => assembly.GetType(typeName) ?? Type.GetType(typeName); } 

MSDN:

https://docs.microsoft.com/ru-ru/dotnet/api/system.type.gettype?view=netcore-2.1#System_Type_GetType_System_Ssortingng_

Je suppose que vous avez oublié de mentionner les espaces de noms. La bonne façon serait

 assembly.GetType(MyNameSpace+sType.Name)