Я вдячний, що це дуже давнє запитання, але я подумав, що буду додати ще одну відповідь для майбутніх користувачів, оскільки всі відповіді на сьогоднішній день використовують певну форму Assembly.GetTypes
.
Хоча GetTypes () дійсно повертає всі типи, це не обов'язково означає, що ви можете їх активувати і, таким чином, потенційно можете кинути a ReflectionTypeLoadException
.
Класичний приклад не в змозі активувати тип буде , коли тип повернутих derived
з , base
але base
визначається в різній комплектації від такого derived
, складального , що викликає збірки не посилань.
Отже, скажімо, у нас є:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Якщо в ClassC
чому знаходиться, AssemblyC
то робимо щось відповідно до прийнятої відповіді:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Тоді він кине а ReflectionTypeLoadException
.
Це відбувається тому , що без посилання AssemblyA
на AssemblyC
вас не буде в змозі:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
Іншими словами, ClassB
це не завантажимо, що є те, що виклик GetTypes перевіряє та накидає.
Отже, щоб безпечно кваліфікувати набір результатів для типів, що завантажуються, відповідно до цієї статті Phil Haacked Отримати всі типи в зборах та код Джона Скета, ви замість цього зробите щось на кшталт:
public static class TypeLoaderExtensions {
public static IEnumerable<Type> GetLoadableTypes(this Assembly assembly) {
if (assembly == null) throw new ArgumentNullException("assembly");
try {
return assembly.GetTypes();
} catch (ReflectionTypeLoadException e) {
return e.Types.Where(t => t != null);
}
}
}
І потім:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}