Как предотвратить ReflectionTypeLoadException при вызове Assembly.GetTypes ()

Я пытаюсь отсканировать сборку для типов, реализующих определенный интерфейс, используя код, подобный этому:

public List FindTypesImplementing(string 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; } 

Моя проблема заключается в том, что я получаю asm.GetTypes() ReflectionTypeLoadException при вызове asm.GetTypes() в некоторых случаях, например, если assembly содержит типы, ссылающиеся на сборку, которая в настоящее время недоступна.

В моем случае меня не интересуют типы, которые вызывают проблему. Типы, которые я ищу, не нуждаются в недоступных assemblyх.

Возникает вопрос: возможно ли каким-то образом пропускать / игнорировать типы, вызывающие исключение, но все же обрабатывать другие типы, содержащиеся в сборке?

Один довольно неприятный способ:

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

Это определенно раздражает, что нужно это делать. Вы можете использовать метод расширения, чтобы сделать его более приятным в «клиентском» коде:

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

Возможно, вы захотите перенести оператор return из блока catch – я не очень увлечен тем, что он сам, но это, вероятно , самый короткий код …

Хотя кажется, что ничего не может быть сделано без получения ReflectionTypeLoadException в какой-то момент, ответы, приведенные выше, ограничены тем, что любая попытка использовать типы, предоставленные из исключения, по-прежнему будет иметь проблему с исходной проблемой, из-за которой тип не загружается.

Чтобы преодолеть это, следующий код ограничивает типы теми, которые расположены в сборке, и позволяет предикату дополнительно ограничивать список типов.

  ///  /// 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; } 

Вы рассматривали Assembly.ReflectionOnlyLoad ? Учитывая то, что вы пытаетесь сделать, этого может быть достаточно.

В моем случае та же проблема была вызвана наличием нежелательных сборок в папке приложения. Попробуйте очистить папку Bin и перестроить приложение.

  • «Требуется Gradle Version 2.10». Ошибка
  • Внедрение архитектуры плагинов / системы плагинов / сменных фреймов в Angular 2, 4, 5, 6
  • Архитектура подключаемого модуля для ASP.NET MVC
  • Рекомендуемые дополнения / плагины для Microsoft Visual Studio
  • Библиотека загрузки DLL - код ошибки 126
  • Как установить плагины в редактор Sublime Text 2?
  • Давайте будем гением компьютера.