我试图通过反射对类的接口执行查询,但是方法Type.GetInterfaces()也返回所有继承的接口。
等
public class Test : ITest { }
public interface ITest : ITesting { }
代码
typeof(Test).GetInterfaces();
将返回包含Type[]
和ITest
的{{1}},其中我只想要ITesting
,是否有另一种方法可以指定继承?
谢谢, 亚历克斯。
编辑: 从下面的答案我收集了这个,
ITest
以上似乎有效,如果不是
,请在评论中纠正我答案 0 :(得分:8)
您可以尝试这样的事情:
Type[] allInterfaces = typeof(Test).GetInterfaces();
var exceptInheritedInterfaces = allInterfaces.Except(
allInterfaces.SelectMany(t => t.GetInterfaces())
);
我认为有一种更优雅的方式,但我现在想不到它......
所以,如果你有这样的事情:
public interface A : B
{
}
public interface B : C
{
}
public interface C
{
}
public interface D
{
}
public class MyType : A, D
{
}
代码将返回 A 和 D
答案 1 :(得分:4)
如果我错了,一位更大的.NET专家可以纠正我,但我不相信这是可能的。在内部,我认为.NET框架实际上并不维护该层次结构,并且在编译为IL代码时会变得扁平化。
例如,C#代码:
class Program : I2
{
static void Main(string[] args)
{
}
}
interface I1
{
}
interface I2 : I1
{
}
在IL代码中构建后,它是:
.class private auto ansi beforefieldinit ReflectionTest.Program
extends [mscorlib]System.Object
implements ReflectionTest.I2,
ReflectionTest.I1
{
...
与class Program : I1, I2
然而,在IL中也是:
.class interface private abstract auto ansi ReflectionTest.I2
implements ReflectionTest.I1
{
...
这意味着您可以编写一些逻辑来从I1
类中获取(来自我的示例)I2
和Program
,然后查询每个接口以查看它们是否实现了一个其他人......
换句话说,由于typeof(I2).GetInterfaces()
包含I1
,因此您可以推断,因为typeof(Program).GetInterfaces()
返回I1
和I2
,然后Program
可能不能直接在代码中继承I1
。
我强调可能不会,因为这也是有效的C#代码,并且会生成相同的IL代码(以及相同的反射结果):
class Program : I1, I2
{
static void Main(string[] args)
{
}
}
interface I1
{
}
interface I2 : I1
{
}
现在Program
直接和间接都继承了I1
...
答案 2 :(得分:2)
无法简单地检索直接接口,但我们有必要的类型元数据来计算出来。
如果我们从整个继承链中得到一个扁平的接口列表,并且每个接口都可以告诉我们它的哪个兄弟节点也实现/要求(他们这样做),我们可以递归地删除所有已实现或需要的接口。父母。
这种做法有点过于激进,因为如果你在直接上课时宣布IFoo
和IBar
并且IFoo
需要IBar
,那么它将是删除(但实际上,这不仅仅是一种好奇心的练习?这对我来说还不清楚......)
这段代码很难看,但我只是把它放在一个新的/裸MonoDevelop安装中......
public static void Main (string[] args)
{
var nonInheritedInterfaces = typeof(Test).GetImmediateInterfaces();
foreach(var iface in nonInheritedInterfaces)
{
Console.WriteLine(iface);
}
Console.Read();
}
class Test : ITest { }
interface ITest : ITestParent { }
interface ITestParent { }
public static class TypeExtensions
{
public static Type[] GetImmediateInterfaces(this Type type)
{
var allInterfaces = type.GetInterfaces();
var nonInheritedInterfaces = new HashSet<Type>(allInterfaces);
foreach(var iface in allInterfaces)
{
RemoveInheritedInterfaces(iface, nonInheritedInterfaces);
}
return nonInheritedInterfaces.ToArray();
}
private static void RemoveInheritedInterfaces(Type iface, HashSet<Type> ifaces)
{
foreach(var inheritedIface in iface.GetInterfaces())
{
ifaces.Remove(inheritedIface);
RemoveInheritedInterfaces(inheritedIface, ifaces);
}
}
}
private static void RemoveInheritedInterfaces(Type iface, Dictionary<Type, Type> interfaces)
{
foreach(var inheritedInterface in iface.GetInterfaces())
{
interfaces.Remove(inheritedInterface);
RemoveInheritedInterfaces(inheritedInterface, interfaces);
}
}
答案 3 :(得分:1)
在我之前的尝试中,我无法成功。
Type[] types = typeof(Test).GetInterfaces();
var directTypes = types.Except
(types.SelectMany(t => t.GetInterfaces()));
foreach (var t in directTypes)
{
}
希望这会对某人有所帮助。
答案 4 :(得分:1)
似乎没有简单的方法调用来执行此操作,因为基本上以下内容在编译时完全相同:
MyClass : IEnumerable<bool>
和
MyClass : IEnumerable<bool>,IEnumerable
您可以询问每个接口并询问其接口。并查看它们是否在former列表中。不同寻常的是,类GetInterfaces是递归的。也就是说它获得了所有级别的继承。对于接口,它不是递归的。例如:
IList
会返回IList
和ICollection
,但不会提及由IEnumerable
实施的ICollection
。
但是,您很可能对每个接口及其绑定唯一实现的方法感兴趣,在这种情况下,您可以使用方法GetInterfaceMap(Type)
。
答案 5 :(得分:0)
试试这个:
Type t = typeof(Test);
int max = 0;
Type result = null;
foreach (Type type in t.GetInterfaces())
{
int len = type.GetInterfaces().Length;
if (len > max)
{
max = len;
result = type;
}
}
if (result != null)
Console.WriteLine(result.FullName);
答案 6 :(得分:0)
Type t = typeof(Test);
int max = 0;
List<Type> results = new List<Type>();
foreach (Type type in t.GetInterfaces())
{
int len = type.GetInterfaces().Length;
if (len > max)
{
max = len;
results.Add(type);
}
}
if (results.Count > 0)
foreach (Type type in results)
Console.WriteLine(type.FullName);