使用反射,我如何能得到所有类型的实现接口与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
当前回答
编辑:我刚刚看到了编辑,澄清了最初的问题是为了减少迭代/代码,这作为一个练习是很好的,但在实际情况下,你会想要最快的实现,不管底层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;
}
我承认,这并不漂亮。
其他回答
你可以使用一些LINQ来获取列表:
var types = from type in this.GetType().Assembly.GetTypes()
where type is ISomeInterface
select type;
但说真的,这样更有可读性吗?
在选择组装位置时就更好了。如果您知道所有实现的接口都在同一个Assembly.DefinedTypes中,则可以筛选大多数程序集。
// We get the assembly through the base class
var baseAssembly = typeof(baseClass).GetTypeInfo().Assembly;
// we filter the defined classes according to the interfaces they implement
var typeList = baseAssembly.DefinedTypes.Where(type => type.ImplementedInterfaces.Any(inter => inter == typeof(IMyInterface))).ToList();
文/詹·比尔金
如果它能帮助任何人,这是我正在使用的使我的一些单元测试更容易:)
public static Type GetInterfacesImplementation(this Type type)
{
return type.Assembly.GetTypes()
.Where(p => type.IsAssignableFrom(p) && !p.IsInterface)
.SingleOrDefault();
}
查找程序集中实现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实现者。
我在linq-code中得到了异常,所以我这样做(没有复杂的扩展):
private static IList<Type> loadAllImplementingTypes(Type[] interfaces)
{
IList<Type> implementingTypes = new List<Type>();
// find all types
foreach (var interfaceType in interfaces)
foreach (var currentAsm in AppDomain.CurrentDomain.GetAssemblies())
try
{
foreach (var currentType in currentAsm.GetTypes())
if (interfaceType.IsAssignableFrom(currentType) && currentType.IsClass && !currentType.IsAbstract)
implementingTypes.Add(currentType);
}
catch { }
return implementingTypes;
}