推理.var classTypesImplementingInterface = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).其中(mytype => typeof(myInterface).IsAssignableFrom(mytype)&& mytype.GetInterfaces().Contains(typeof(myInterface) )); foreach(项目中的var项)Console.Log(item.Name);
3> Judah Gabrie..:
要查找实现IFoo接口的程序集中的所有类型:
var results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
请注意,Ryan Rinaldi的建议不正确.它将返回0种类型.你不能写
where type is IFoo
因为type是System.Type实例,并且永远不会是IFoo类型.而是检查是否可以从类型中分配IFoo.这将获得您的预期结果.
此外,Adam Wright的建议,目前被标记为答案,也是不正确的,并且出于同样的原因.在运行时,您将看到0种类型返回,因为所有System.Type实例都不是IFoo实现者.
4> rism..:
我很欣赏这是一个非常古老的问题,但我想我会为未来的用户添加另一个答案,因为所有日期答案都使用某种形式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 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 GetTypesWithInterface(Assembly asm) {
var it = typeof (IMyInterface);
return asm.GetLoadableTypes().Where(it.IsAssignableFrom).ToList();
}
这有助于我处理一个超级奇怪的问题,在我的测试项目中GetTypes会失败,只在我们的CI环境中.GetLoadableTypes是此解决方案的修复程序.该错误在本地环境中不可重现,它是:System.Reflection.ReflectionTypeLoadException:无法加载一个或多个请求的类型.检索LoaderExceptions属性以获取更多信息.更具体地说,它抱怨有一种没有具体实施的类型,它发生在单元测试项目中.谢谢你!
万一它对其他人有帮助:这个解决方案对我有用,但是我必须对其进行修改以从列表中删除接口类型。我想为所有它们都激活`CreateInstance`,并且在尝试创建实际接口时引发了异常(当我认为实际接口不适合该解决方案时,这让我感到困惑)。所以我将代码更改为`GetLoadableTypes(assembly).Where(interfaceType.IsAssignableFrom).Where(t =>!(t.Equals(interfaceType)))。ToList();`。
5> hillstuk..:
其他答案在这里使用IsAssignableFrom
.您也可以使用FindInterfaces
从System
命名空间,如所描述这里.
下面是一个示例,它检查当前正在执行的程序集文件夹中的所有程序集,查找实现某个接口的类(为清楚起见,避免使用LINQ).
static void Main() {
const string qualifiedInterfaceName = "Interfaces.IMyInterface";
var interfaceFilter = new TypeFilter(InterfaceFilter);
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
var di = new DirectoryInfo(path);
foreach (var file in di.GetFiles("*.dll")) {
try {
var nextAssembly = Assembly.ReflectionOnlyLoadFrom(file.FullName);
foreach (var type in nextAssembly.GetTypes()) {
var myInterfaces = type.FindInterfaces(interfaceFilter, qualifiedInterfaceName);
if (myInterfaces.Length > 0) {
// This class implements the interface
}
}
} catch (BadImageFormatException) {
// Not a .net assembly - ignore
}
}
}
public static bool InterfaceFilter(Type typeObj, Object criteriaObj) {
return typeObj.ToString() == criteriaObj.ToString();
}
如果要匹配多个接口,可以设置接口列表.
6> angry person..:
循环遍历所有已加载的程序集,遍历所有类型,并检查它们是否实现了接口.
就像是:
Type ti = typeof(IYourInterface);
foreach (Assembly asm in AppDomain.CurrentDomain.GetAssemblies()) {
foreach (Type t in asm.GetTypes()) {
if (ti.IsAssignableFrom(t)) {
// here's your type in t
}
}
}
7> 小智..:
这对我有用(如果你希望你可以在查找中排除系统类型):
Type lookupType = typeof (IMenuItem);
IEnumerable lookupTypes = GetType().Assembly.GetTypes().Where(
t => lookupType.IsAssignableFrom(t) && !t.IsInterface);
8> tags2k..:
编辑:我刚刚看到编辑,以澄清原始问题是减少迭代/代码,这一切都很好,作为一个练习,但在现实世界的情况下,你将希望最快的实现,无论如何底层LINQ看起来有多酷.
这是我的Utils方法,用于迭代加载的类型.它处理常规类和接口,如果您在自己的/第三方代码库中寻找实现,则excludeSystemTypes选项可以大大加快速度.
public static List GetSubclassesOf(this Type type, bool excludeSystemTypes) {
List list = new List();
IEnumerator enumerator = Thread.GetDomain().GetAssemblies().GetEnumerator();
while (enumerator.MoveNext()) {
try {
Type[] types = ((Assembly) enumerator.Current).GetTypes();
if (!excludeSystemTypes || (excludeSystemTypes && !((Assembly) enumerator.Current).FullName.StartsWith("System."))) {
IEnumerator enumerator2 = types.GetEnumerator();
while (enumerator2.MoveNext()) {
Type current = (Type) enumerator2.Current;
if (type.IsInterface) {
if (current.GetInterface(type.FullName) != null) {
list.Add(current);
}
} else if (current.IsSubclassOf(type)) {
list.Add(current);
}
}
}
} catch {
}
}
return list;
}
我承认,它不漂亮.
枚举器实现IDisposable,它不会在try/finally中处理.最好使用foreach或linq.