ฉันขอขอบคุณที่นี้เป็นคำถามที่เก่ามาก Assembly.GetTypes
แต่ฉันคิดว่าฉันจะเพิ่มคำตอบอื่นสำหรับผู้ใช้ในอนาคตเช่นทุกคำตอบถึงวันที่ใช้รูปแบบของบางอย่าง
ขณะ GetTypes () 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นี้รับทุกประเภทในแอสเซมบลีและรหัส Jon Skeetคุณจะทำสิ่งที่ต้องการแทน:
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();
}