获取实现接口的所有types

使用reflection,我怎样才能获得所有types的实现与C#3.0 / .NET 3.5与最less的代码,并最小化迭代?

这是我想重写的内容:

foreach (Type t in this.GetType().Assembly.GetTypes()) if (t is IMyInterface) ; //do stuff 

我的将在c#3.0中为此:)

 var type = typeof(IMyInterface); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => type.IsAssignableFrom(p)); 

基本上,最小的迭代总是:

 loop assemblies loop types see if implemented. 

要在实现IFoo接口的程序集中查找所有types:

 var results = from type in someAssembly.GetTypes() where typeof(IFoo).IsAssignableFrom(type) select type; 

请注意Ryan Rinaldi的build议是不正确的。 它将返回0types。 你不能写

 where type is IFoo 

因为type是一个System.Type实例,永远不会是IFootypes的。 而是检查IFoo是否可以从types中分配。 这将得到您的预期结果。

此外,亚当·赖特(Adam Wright)的build议目前也被认为是答案,也是不正确的,同样的原因。 在运行时,你会看到0个types返回,因为所有的System.Type实例都不是IFoo实现者。

这对我有效。 它循环虽然类和检查,看它们是否从myInterface derrived

  foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes() .Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) { //do stuff } 

我很欣赏这是一个非常古老的问题,但我想我会为未来的用户添加另一个答案,因为所有迄今为止的答案使用某种forms的Assembly.GetTypes

虽然GetTypes()确实会返回所有types,但并不一定意味着可以激活它们,因此可能会抛出ReflectionTypeLoadException

不能激活一个types的典型例子是当返回的types是从base derived ,但是base是在derived的不同的程序集中定义的,调用程序集没有引用的程序集。

所以说我们有:

 Class A // in AssemblyA Class B : Class A, IMyInterface // in AssemblyB Class C // in AssemblyC which references AssemblyB but not AssemblyA 

如果在ClassC中的ClassC ,我们按照接受的答案做一些事情:

 var type = typeof(IMyInterface); var types = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(s => s.GetTypes()) .Where(p => type.IsAssignableFrom(p)); 

然后它会抛出一个ReflectionTypeLoadException

这是因为在AssemblyC没有提及AssemblyA ,您将无法:

 var bType = typeof(ClassB); var bClass = (ClassB)Activator.CreateInstance(bType); 

换句话说, ClassB不可加载 ,这是对GetTypes的调用进行检查和抛出的东西。

因此,为了安全地限定可加载types的结果集,然后按照Phil Haacked的文章“在Assembly中获取所有types”和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(); } 

其他答案在这里使用IsAssignableFrom 。 您也可以使用System命名空间中的FindInterfaces ,如此处所述。

下面是一个例子,它检查当前正在执行的程序集文件夹中的所有程序集,查找实现某个接口的类(避免使用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(); } 

如果要匹配多个接口,可以设置接口列表。

遍历所有加载的程序集,遍历所有types,并检查它们是否实现了接口。

就像是:

 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 } } } 

这对我有用(如果你希望你可以在查找中排除系统types):

 Type lookupType = typeof (IMenuItem); IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where( t => lookupType.IsAssignableFrom(t) && !t.IsInterface); 

编辑:我刚刚看到编辑澄清,原来的问题是减less迭代/代码,这一切都很好,作为一个练习,但在现实世界的情况下,你会想要最快的实现,无论底层LINQ看起来有多酷。

这是我的Utils方法迭代通过加载的types。 它处理常规类以及接口,如果您正在寻找自己/第三方代码库中的实现,则excludeSystemTypes选项将大大加快速度。

 public static List<Type> GetSubclassesOf(this Type type, bool excludeSystemTypes) { List<Type> list = new List<Type>(); 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; } 

这不是很美,我承认。

没有简单的方法(在性能方面)做你想做的事情。

reflection主要用于组件和types,因此您必须获取程序集的所有types,并查询它们以获取正确的界面。 这是一个例子:

 Assembly asm = Assembly.Load("MyAssembly"); Type[] types = asm.GetTypes(); Type[] result = types.where(x => x.GetInterface("IMyInterface") != null); 

这将为您带来在Assembly MyAssembly中实现IMyInterface的所有types

你可以使用一些LINQ来获取列表:

 var types = from type in this.GetType().Assembly.GetTypes() where type is ISomeInterface select type; 

但是,真的,这是更可读?