使用反射,我如何能得到所有类型的实现接口与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
当前回答
(就性能而言)做你想做的事情并不容易。
反射主要使用程序集和类型,因此您必须获取程序集的所有类型并查询它们以获得正确的接口。这里有一个例子:
Assembly asm = Assembly.Load("MyAssembly");
Type[] types = asm.GetTypes();
Type[] result = types.where(x => x.GetInterface("IMyInterface") != null);
这将为您提供在程序集MyAssembly中实现IMyInterface的所有类型
其他回答
编辑:我刚刚看到了编辑,澄清了最初的问题是为了减少迭代/代码,这作为一个练习是很好的,但在实际情况下,你会想要最快的实现,不管底层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;
}
我承认,这并不漂亮。
我的是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.
其他答案是没有使用通用接口。
这一个做到了,只是用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();
把它们列在一个列表里。
如果它能帮助任何人,这是我正在使用的使我的一些单元测试更容易:)
public static Type GetInterfacesImplementation(this Type type)
{
return type.Assembly.GetTypes()
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface)
.SingleOrDefault();
}
OfType Linq方法正好可以用于这种场景:
https://learn.microsoft.com/fr-fr/dotnet/api/system.linq.enumerable.oftype?view=netframework-4.8