获取实现接口的所有类型
时间:2020-03-05 18:42:58 来源:igfitidea点击:
使用反射,如何以最少的代码获得所有实现与C3.0 / .NET 3.5接口的类型,并最大程度地减少迭代次数?
这是我要重写的内容:
foreach (Type t in this.GetType().Assembly.GetTypes()) if (t is IMyInterface) ; //do stuff
解决方案
回答
遍历所有已加载的程序集,遍历所有类型,并检查它们是否实现了接口。
就像是:
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 } } }
回答
我在c3.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.
回答
编辑:我刚刚看过编辑,以澄清原来的问题是减少迭代/代码,并且作为练习很好,但是在现实世界中,无论哪种情况,我们都希望最快的实现底层LINQ看起来有多酷。
这是我的Utils方法,用于遍历已加载的类型。它处理常规类和接口,如果要在自己的/第三方代码库中寻找实现,则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; }
我承认,这并不漂亮。
回答
没有简单的方法(就性能而言)来完成我们想做的事情。
反射主要与程序集和类型一起使用,因此我们必须获取程序集的所有类型并向其查询正确的接口。这是一个例子:
Assembly asm = Assembly.Load("MyAssembly"); Type[] types = asm.GetTypes(); Type[] result = types.where(x => x.GetInterface("IMyInterface") != null);
这将为我们提供在Assembly MyAssembly中实现IMyInterface的所有类型。
回答
我们可以使用一些LINQ来获取列表:
var types = from type in this.GetType().Assembly.GetTypes() where type is ISomeInterface select type;
但是,确实更具可读性吗?
回答
要在实现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。那会得到我们预期的结果。
同样,出于同样的原因,目前被标记为答案的亚当·赖特的建议也是错误的。在运行时,我们会看到0类型返回,因为所有System.Type实例都不是IFoo实现者。
回答
这对我有用(如果我们希望可以在查找中排除系统类型):
Type lookupType = typeof (IMenuItem); IEnumerable<Type> lookupTypes = GetType().Assembly.GetTypes().Where( t => lookupType.IsAssignableFrom(t) && !t.IsInterface);