Tôi đánh giá cao đây là một câu hỏi rất cũ nhưng tôi nghĩ rằng tôi sẽ thêm một câu trả lời khác cho người dùng trong tương lai vì tất cả các câu trả lời cho đến nay đều sử dụng một số hình thức Assembly.GetTypes
.
Trong khi GetTypes () thực sự sẽ trả về tất cả các loại, điều đó không nhất thiết có nghĩa là bạn có thể kích hoạt chúng và do đó có khả năng ném một ReflectionTypeLoadException
.
Một ví dụ điển hình cho việc không thể kích hoạt một loại sẽ là khi loại trở lại là derived
từ base
nhưng base
được định nghĩa trong một hội đồng khác với derived
, tham khảo một hội rằng gọi lắp ráp thì không.
Vì vậy, nói rằng chúng ta có:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
Nếu trong ClassC
đó là trong AssemblyC
chúng ta sau đó làm một cái gì đó theo câu trả lời được chấp nhận:
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
Rồi nó sẽ ném a ReflectionTypeLoadException
.
Điều này là do không có tài liệu tham khảo AssemblyA
trong AssemblyC
bạn sẽ không thể:
var bType = typeof(ClassB);
var bClass = (ClassB)Activator.CreateInstance(bType);
Nói cách khác, ClassB
không thể tải được , đó là điều mà lệnh gọi GetTypes kiểm tra và thực hiện.
Vì vậy, để đủ điều kiện an toàn kết quả được đặt cho các loại có thể tải sau đó, theo bài viết này Phil Haacked Nhận tất cả các loại trong một hội và mã Jon Skeet, thay vào đó bạn sẽ làm một cái gì đó như:
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);
}
}
}
Và sau đó:
private IEnumerable<Type> GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}