Comment faire pour empêcher ReflectionTypeLoadException lorsqu ‘appeler Assembly.GetTypes ()

J’essaie d’parsingr un assemblage pour les types implémentant une interface spécifique en utilisant un code similaire à celui-ci:

public List FindTypesImplementing(ssortingng assemblyPath) { var matchingTypes = new List(); var asm = Assembly.LoadFrom(assemblyPath); foreach (var t in asm.GetTypes()) { if (typeof(T).IsAssignableFrom(t)) matchingTypes.Add(t); } return matchingTypes; } 

Mon problème est que je reçois une asm.GetTypes() ReflectionTypeLoadException lorsque asm.GetTypes() dans certains cas, par exemple si l’assembly contient des types référençant un assembly qui n’est actuellement pas disponible.

Dans mon cas, je ne suis pas intéressé par les types qui causent le problème. Les types recherchés ne nécessitent pas les assemblages non disponibles.

La question est: est-il possible de sauter / ignorer d’une manière ou d’une autre les types qui provoquent l’exception mais traitent quand même les autres types contenus dans l’assembly?

Un moyen assez méchant serait:

 Type[] types; try { types = asm.GetTypes(); } catch (ReflectionTypeLoadException e) { types = e.Types; } foreach (var t in types.Where(t => t != null)) { ... } 

C’est vraiment ennuyeux de devoir faire ça. Vous pouvez utiliser une méthode d’extension pour la rendre plus agréable dans le code “client”:

 public static IEnumerable GetLoadableTypes(this Assembly assembly) { // TODO: Argument validation try { return assembly.GetTypes(); } catch (ReflectionTypeLoadException e) { return e.Types.Where(t => t != null); } } 

Vous voudrez peut-être déplacer la déclaration de return hors du bloc catch – je ne suis pas très enthousiaste à l’idée d’y être, mais c’est probablement le code le plus court …

Bien qu’il semble que rien ne puisse être fait sans recevoir ReflectionTypeLoadException à un moment donné, les réponses ci-dessus sont limitées en ce sens que toute tentative d’utilisation des types fournis à partir de l’exception pose toujours le problème d’origine.

Pour résoudre ce problème, le code suivant limite les types à ceux situés dans l’assembly et permet à un prédicat de restreindre davantage la liste des types.

  ///  /// Get the types within the assembly that match the predicate. /// for example, to get all types within a namespace ///  typeof(SomeClassInAssemblyYouWant).Assembly.GetMatchingTypesInAssembly(item => "MyNamespace".Equals(item.Namespace)) ///  /// The assembly to search /// The predicate query to match against /// The collection of types within the assembly that match the predicate public static ICollection GetMatchingTypesInAssembly(this Assembly assembly, Predicate predicate) { ICollection types = new List(); try { types = assembly.GetTypes().Where(i => i != null && predicate(i) && i.Assembly == assembly).ToList(); } catch (ReflectionTypeLoadException ex) { foreach (Type theType in ex.Types) { try { if (theType != null && predicate(theType) && theType.Assembly == assembly) types.Add(theType); } // This exception list is not exhaustive, modify to suit any reasons // you find for failure to parse a single assembly catch (BadImageFormatException) { // Type not in this assembly - reference to elsewhere ignored } } } return types; } 

Avez-vous considéré Assembly.ReflectionOnlyLoad ? Compte tenu de ce que vous essayez de faire, cela pourrait suffire.

Dans mon cas, le même problème était dû à la présence d’assemblages indésirables dans le dossier de l’application. Essayez d’effacer le dossier Bin et de reconstruire l’application.