foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
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.
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface);
以过滤掉它(或者使用p.IsClass
)。 - jtpereydaList<string>
没有实现IEnumerable<object>
,但是由于.NET 4.0中支持协变,此方法将返回true,这是错误的。正确答案在这里。 - Sriram Sakthivel.Where(p => type.IsAssignableFrom(p) && p.IsClass && !p.IsAbstract
- Jonesopolis这对我有用。它循环遍历类并检查它们是否派生自myInterface。
foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes()
.Where(mytype => mytype .GetInterfaces().Contains(typeof(myInterface)))) {
//do stuff
}
.IsAssignableFrom(..)
可能更安全。 - eternal_frame其他答案使用了一些形式的Assembly.GetTypes
。
虽然GetTypes()确实会返回所有类型,但这并不意味着您可以激活它们,因此可能会抛出ReflectionTypeLoadException
。
一个无法激活类型的经典例子是,当返回的类型从base
派生而来,但base
在与derived
不同的程序集中定义,而调用程序集没有引用该程序集时。
所以说我们有:
Class A // in AssemblyA
Class B : Class A, IMyInterface // in AssemblyB
Class C // in AssemblyC which references AssemblyB but not AssemblyA
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进行检查并抛出的内容。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();
}
CreateInstance
,但当它尝试创建实际接口时(当我认为实际接口已经在此解决方案中了一段时间)抛出了异常,这让我感到困惑。所以我将代码更改为 GetLoadableTypes(assembly).Where(interfaceType.IsAssignableFrom).Where(t => !(t.Equals(interfaceType))).ToList();
。 - Xavier Peñavar results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
请注意,Ryan Rinaldi的建议是不正确的。它会返回0个类型。您不能编写:Note that Ryan Rinaldi's suggestion was incorrect. It will return 0 types. You cannot write
。where type is IFoo
因为 type 是 System.Type 的实例,并且永远不会是 IFoo 类型。相反,您需要检查 IFoo 是否可以从该类型分配。这将得到您期望的结果。
此外,Adam Wright 的建议(当前标记为答案)也是错误的,原因相同。在运行时,您将看到返回 0 种类型,因为所有 System.Type 实例都不是 IFoo 实现者。
这里的其他答案使用了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();
}
如果你想匹配多个接口,可以设置一个接口列表。
遍历所有已加载的程序集,循环遍历它们的类型,并检查它们是否实现了接口。
类似于以下代码:
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
}
}
}
Type lookupType = typeof (IMenuItem);
IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where(
t => lookupType.IsAssignableFrom(t) && !t.IsInterface);
其他答案无法适用于通用接口。
这个可以,只需将 typeof(ISomeInterface) 替换为 typeof(T)。
List<string> types = AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
.Where(x => typeof(ISomeInterface).IsAssignableFrom(x) && !x.IsInterface && !x.IsAbstract)
.Select(x => x.Name).ToList();
So with
AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
!x.IsInterface && !x.IsAbstract
用于排除接口和抽象类。
.Select(x => x.Name).ToList();
将它们列在一个列表中。
我看到这里有很多过于复杂的回答,人们总是告诉我我往往把事情复杂化了。此外,使用 IsAssignableFrom
方法解决 OP 问题是错误的!
下面是我的例子,它选择应用程序域中的所有程序集,然后获取所有可用类型的平面列表,并检查每个单独类型的接口列表以进行匹配:
public static IEnumerable<Type> GetImplementingTypes(this Type itype)
=> AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
.Where(t => t.GetInterfaces().Contains(itype));
public static class ReflectionUtils
{
public static bool DoesTypeSupportInterface(Type type, Type inter)
{
if (inter.IsAssignableFrom(type))
return true;
if (type.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == inter))
return true;
return false;
}
public static IEnumerable<Assembly> GetReferencingAssemblies(Assembly assembly)
{
return AppDomain
.CurrentDomain
.GetAssemblies().Where(asm => asm.GetReferencedAssemblies().Any(asmName => AssemblyName.ReferenceMatchesDefinition(asmName, assembly.GetName())));
}
public static IEnumerable<Type> TypesImplementingInterface(Type desiredType)
{
var assembliesToSearch = new Assembly[] { desiredType.Assembly }
.Concat(GetReferencingAssemblies(desiredType.Assembly));
return assembliesToSearch.SelectMany(assembly => assembly.GetTypes())
.Where(type => DoesTypeSupportInterface(type, desiredType));
}
public static IEnumerable<Type> NonAbstractTypesImplementingInterface(Type desiredType)
{
return TypesImplementingInterface(desiredType).Where(t => !t.IsAbstract);
}
}