如何在调用Assembly.GetTypes()时防止ReflectionTypeLoadException

我试图扫描程序集的types实现一个特定的接口使用类似于这样的代码:

public List<Type> FindTypesImplementing<T>(string assemblyPath) { var matchingTypes = new List<Type>(); 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()包含引用当前不可用的程序集的types。

就我而言,我对引起问题的types不感兴趣。 我正在search的types不需要不可用的程序集。

问题是:有可能以某种方式跳过/忽略导致exception的types,但仍处理程序集中包含的其他types?

一个相当讨厌的方法是:

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

这绝对是烦人的,但必须这样做。 你可以使用扩展方法在“客户端”代码中使其更好:

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

你可能希望将return声明从catch块中移出 – 我不是非常热衷于它自己,但它可能最短的代码…

虽然看起来在没有收到ReflectionTypeLoadException的情况下没有什么可以做的,但是上面的答案是有限的,因为任何试图利用exception提供的types的尝试仍然会导致导致types加载失败的原始问题。

为了克服这个问题,下面的代码将types限制为位于程序集内的types,并允许谓词进一步限制types列表。

  /// <summary> /// Get the types within the assembly that match the predicate. /// <para>for example, to get all types within a namespace</para> /// <para> typeof(SomeClassInAssemblyYouWant).Assembly.GetMatchingTypesInAssembly(item => "MyNamespace".Equals(item.Namespace))</para> /// </summary> /// <param name="assembly">The assembly to search</param> /// <param name="predicate">The predicate query to match against</param> /// <returns>The collection of types within the assembly that match the predicate</returns> public static ICollection<Type> GetMatchingTypesInAssembly(this Assembly assembly, Predicate<Type> predicate) { ICollection<Type> types = new List<Type>(); 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文件夹并重build应用程序。