C#中如何查找实现泛型接口IWork<T>的所有类(排除接口自身)
如何排除反射查询中泛型接口自身的结果?
我懂你现在碰到的问题——用反射查找所有实现IWork<T>的类型时,结果里居然把接口本身也包含进来了,这肯定不是你想要的。其实问题出在IsAssignableFrom的判断逻辑上:它会认为接口可以赋值给自己,所以我们只需要给查询加几个过滤条件就能搞定。
问题根源
当你调用type.IsAssignableFrom(p)时,对于IWork<>这个接口类型本身,这个判断会返回true——因为任何类型都能"赋值给自己",包括接口。所以我们需要在筛选条件里加上规则,把接口本身和其他非具体实现类排除掉。
解决方案
修改你的查询语句,加入以下几个关键过滤条件:
var type = typeof(IWork<>); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => !p.IsAbstract // 排除抽象类和接口这类无法实例化的类型 && !p.IsInterface // 明确排除所有接口类型 && type.IsAssignableFrom(p) // 保留真正实现了目标接口的类型 && p != type // 双重保险,直接排除接口自身 );
条件解释
!p.IsAbstract:抽象类和接口都属于抽象类型,我们要找的是可以实例化的具体实现类,所以先把它们排除!p.IsInterface:直接过滤掉所有接口类型,从根源上避免把IWork<>本身选进来p != type:这是额外的保险措施,就算前面的条件有疏漏,也能确保目标接口不会出现在结果里
额外说明
如果你的实现类是泛型类(比如public class GenericWork<T> : IWork<T>),上面的代码也能正确识别它,因为IsAssignableFrom对泛型类型的匹配是有效的。举个例子,假设你有这些实现:
public class OrderProcessor : IWork<Order> { /* ... */ } public class GenericProcessor<T> : IWork<T> { /* ... */ }
修改后的查询会把这两个具体类都找出来,同时完美排除IWork<>接口本身。
另外提一句:如果你的项目有延迟加载程序集的情况,要确保所有包含实现类的程序集都已经加载到当前AppDomain中,不然GetAssemblies()可能找不到它们——不过这是另一个场景的问题了,你的核心需求用上面的代码就能解决。
内容的提问来源于stack exchange,提问作者Mohamd Ali
相关产品推荐
相关产品推荐

