只获取直接界面而不是全部?
我有一个类似下面的课程。 GetInterfaces()说
如果当前Type表示generics类型或generics方法的定义中的类型参数,则此方法搜索接口约束以及从类或接口约束inheritance的任何接口。
我有可能没有得到任何inheritance的接口吗? 当我在ABC上使用GetInterfaces时我只想看DEF,而不是DEF和GHI。
interface DEF : GHI {...} class ABC : DEF {...}
首先,您发布的MSDN代码段与您的实际问题没有任何关系。 例如,它处理一个generics类型,如class Foo
,并尝试在类型参数T
上调用GetInterfaces
,例如通过typeof(Foo<>).GetGenericArguments().Single().GetInterfaces().
其次,这个问题略显不明。 请注意,当类实现接口时,它必须实现该接口“inheritance”的所有接口。 它只是一个C#便利function,可以省略类声明中的inheritance接口。 在您的示例中, 明确包含“inheritance的” GHI
接口是完全合法的(并且没有区别):
class ABC : DEF, GHI {...}
我假设你真正想要做的是找到一个“覆盖”所有类型实现的接口的“最小集合”接口。 这导致Set cover问题的略微简化版本。
这是解决它的一种方法,没有任何尝试在算法上有效。 我们的想法是通过过滤那些已由该类型实现的其他接口实现的接口来生成最小接口集。
Type type = ... var allInterfaces = type.GetInterfaces(); var minimalInterfaces = from iType in allInterfaces where !allInterfaces.Any(t => t.GetInterfaces() .Contains(iType)) select iType;
( 编辑 – 这是一个更好的方法来做到这一点:
var minimalInterfaces = allInterfaces.Except (allInterfaces.SelectMany(t => t.GetInterfaces()));
)
例如,对于List
:
allInterfaces: System.Collections.Generic.IList`1[System.Int32] System.Collections.Generic.ICollection`1[System.Int32] System.Collections.Generic.IEnumerable`1[System.Int32] System.Collections.IEnumerable System.Collections.IList System.Collections.ICollection minimalInterfaces: System.Collections.Generic.IList`1[System.Int32] System.Collections.IList
请注意,此解决方案仅涵盖接口 “层次结构”(这是您想要的),而不是它们与类的层次结构的关系。 特别是,它不关注类的层次结构中首次实现接口的位置。
例如,假设我们有:
interface IFoo { } interface IBar : IFoo { } interface IBaz { } class Base : IBar { } class Derived : Base, IBaz { }
现在,如果您尝试使用我所描述的解决方案来获得Derived
的最小接口集,您将获得IBaz
以及IBar
。 如果你不想要IBar
,你将不得不付出更多努力:消除基类实现的接口。 最简单的方法是从最小的接口集中删除由类的直接基类实现的接口,如@ MikeEast的答案中所述。
这是一个重复问题的好文章:
public static class TypeExtensions { public static IEnumerable GetInterfaces(this Type type, bool includeInherited) { if (includeInherited || type.BaseType == null) return type.GetInterfaces(); else return type.GetInterfaces().Except(type.BaseType.GetInterfaces()); } }
用法:
foreach(Type ifc in typeof(Some).GetInterfaces(false)) { Console.WriteLine(ifc); }
同样的MSDN页面说
GetInterfaces方法不以特定顺序返回接口,例如按字母顺序或声明顺序。 您的代码不得依赖于返回接口的顺序,因为该顺序会有所不同。
所以不,你不能跳过接口。
这对接口inheritanceheirachy怎么样?
public static Map GetTypeInheritance(Type type) { //get all the interfaces for this type var interfaces = type.GetInterfaces(); //get all the interfaces for the ancestor interfaces var baseInterfaces = interfaces.SelectMany(i => i.GetInterfaces()); //filter based on only the direct interfaces var directInterfaces = interfaces.Where(i => baseInterfaces.All(b => b != i)); Map map = new Map { Node = type, Ancestors = directInterfaces.Select(GetTypeInheritance).ToList() }; return map; } public class Map { public Type Node { get; set; } public List
这个问题在这里和这里都是重复的。 无论如何,这是我的简洁代码,它考虑了@Ani和@Mikael在这个主题上提出的观点:
var actualInterfaces = type.GetInterfaces(); foreach ( var result in actualInterfaces .Except( type.BaseType?.GetInterfaces() ?? Enumerable.Empty() ) //See https://stackoverflow.com/a/1613936 .Except( actualInterfaces.SelectMany( i => i.GetInterfaces() ) ) //See https://stackoverflow.com/a/5318781 ) yield return result;