Làm thế nào để bạn có được một bộ sưu tập tất cả các loại kế thừa từ một loại cụ thể khác?
Làm thế nào để bạn có được một bộ sưu tập tất cả các loại kế thừa từ một loại cụ thể khác?
Câu trả lời:
Cái gì đó như:
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => baseType.IsAssignableFrom(t));
}
Nếu bạn cần xử lý các generic, điều đó sẽ phức tạp hơn một chút (ví dụ: chuyển vào List<>
kiểu mở nhưng mong đợi nhận lại kiểu có nguồn gốc từ đó List<int>
). Nếu không thì nó rất đơn giản :)
Nếu bạn muốn loại trừ chính loại này, bạn có thể làm như vậy đủ dễ dàng:
public IEnumerable<Type> FindDerivedTypes(Assembly assembly, Type baseType)
{
return assembly.GetTypes().Where(t => t != baseType &&
baseType.IsAssignableFrom(t));
}
Lưu ý rằng điều này cũng sẽ cho phép bạn chỉ định một giao diện và tìm tất cả các kiểu triển khai nó, thay vì chỉ làm việc với các lớp như Type.IsSubclassOf
hiện tại.
IsAssignableFrom
cũng nên hoạt động. Đặc biệt, phiên bản của tôi cũng đối phó với các giao diện. Bạn đã kiểm tra mã của tôi? Trường hợp nào câu trả lời của tôi không thành công?
Phương thức sau sẽ nhận được một tập hợp các kiểu kế thừa một kiểu.
C #
public IEnumerable<Type> FindSubClassesOf<TBaseType>()
{
var baseType = typeof(TBaseType);
var assembly = baseType.Assembly;
return assembly.GetTypes().Where(t => t.IsSubclassOf(baseType));
}
VB.NET
Public Function FindSubClasses(Of TBaseType)() As IEnumerable(Of Type)
Dim baseType = GetType(TBaseType)
Dim assembly = baseType.Assembly
Return From t In assembly.GetTypes()
Where t.IsSubClassOf(baseType)
Select t
End Function
Nếu bạn cần bao gồm các loại triển khai giao diện, hãy xem câu trả lời của @Jon Skeet.
Bạn phải liệt kê tất cả các loại và kiểm tra từng loại nếu nó kế thừa loại mà bạn đang tìm kiếm.
Một số mã như mã trong câu hỏi này có thể hữu ích cho bạn.
Cân nhắc sử dụng phương pháp này (được viết cho PCL):
public IEnumerable<Type> FindDerivedTypes( Assembly assembly, Type baseType )
{
TypeInfo baseTypeInfo = baseType.GetTypeInfo();
bool isClass = baseTypeInfo.IsClass, isInterface = baseTypeInfo.IsInterface;
return
from type in assembly.DefinedTypes
where isClass ? type.IsSubclassOf( baseType ) :
isInterface ? type.ImplementedInterfaces.Contains( baseTypeInfo.AsType() ) : false
select type.AsType();
}