使用反射,我如何能得到所有类型的实现接口与c# 3.0/。NET 3.5用最少的代码,最小化迭代?
这是我想重写的内容:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
使用反射,我如何能得到所有类型的实现接口与c# 3.0/。NET 3.5用最少的代码,最小化迭代?
这是我想重写的内容:
foreach (Type t in this.GetType().Assembly.GetTypes())
if (t is IMyInterface)
; //do stuff
当前回答
其他答案是没有使用通用接口。
这一个做到了,只是用typeof(T)替换typeof(ISomeInterface)。
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();
所以,
AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
我们得到了所有的集合
!x.IsInterface && !x.IsAbstract
是用来排除接口和抽象的和
.Select(x => x.Name).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();
}
如果需要匹配多个接口,可以设置一个接口列表。
OfType Linq方法正好可以用于这种场景:
https://learn.microsoft.com/fr-fr/dotnet/api/system.linq.enumerable.oftype?view=netframework-4.8
我在这里看到了太多过于复杂的答案,人们总是告诉我,我倾向于把事情复杂化。同样使用IsAssignableFrom方法来解决OP问题也是错误的!
下面是我的例子,它从应用程序域中选择所有程序集,然后它采用所有可用类型的平面列表,并检查每个类型的接口列表是否匹配:
public static IEnumerable<Type> GetImplementingTypes(this Type itype)
=> AppDomain.CurrentDomain.GetAssemblies().SelectMany(s => s.GetTypes())
.Where(t => t.GetInterfaces().Contains(itype));
其他答案是没有使用通用接口。
这一个做到了,只是用typeof(T)替换typeof(ISomeInterface)。
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();
所以,
AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes())
我们得到了所有的集合
!x.IsInterface && !x.IsAbstract
是用来排除接口和抽象的和
.Select(x => x.Name).ToList();
把它们列在一个列表里。
查找程序集中实现IFoo接口的所有类型:
var results = from type in someAssembly.GetTypes()
where typeof(IFoo).IsAssignableFrom(type)
select type;
请注意Ryan Rinaldi的建议是不正确的。它将返回0个类型。你不能写字
where type is IFoo
因为类型是一个系统。类型实例,并且永远不会是IFoo类型。相反,检查IFoo是否可以从类型中赋值。这将得到你预期的结果。
此外,亚当·赖特的建议,目前被标记为答案,也是不正确的,出于同样的原因。在运行时,您将看到返回0类型,因为所有System。类型实例不是IFoo实现者。