只查找非继承的接口?

时间:2011-09-27 01:32:53

标签: c# .net reflection .net-4.0 interface

我试图通过反射对类的接口执行查询,但是方法Type.GetInterfaces()也返回所有继承的接口。

public class Test : ITest { }

public interface ITest : ITesting { }

代码

typeof(Test).GetInterfaces();

将返回包含Type[]ITest的{​​{1}},其中我只想要ITesting,是否有另一种方法可以指定继承?

谢谢, 亚历克斯。

编辑: 从下面的答案我收集了这个,

ITest

以上似乎有效,如果不是

,请在评论中纠正我

7 个答案:

答案 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类中获取(来自我的示例)I2Program,然后查询每个接口以查看它们是否实现了一个其他人...... 换句话说,由于typeof(I2).GetInterfaces()包含I1,因此您可以推断,因为typeof(Program).GetInterfaces()返回I1I2,然后Program 可能不能直接在代码中继承I1

我强调可能不会,因为这也是有效的C#代码,并且会生成相同的IL代码(以及相同的反射结果):

class Program : I1, I2
{
    static void Main(string[] args)
    {
    }
}

interface I1
{
}

interface I2 : I1
{
}

现在Program直接和间接都继承了I1 ...

答案 2 :(得分:2)

无法简单地检索直接接口,但我们有必要的类型元数据来计算出来。

如果我们从整个继承链中得到一个扁平的接口列表,并且每个接口都可以告诉我们它的哪个兄弟节点也实现/要求(他们这样做),我们可以递归地删除所有已实现或需要的接口。父母。

这种做法有点过于激进,因为如果你在直接上课时宣布IFooIBar并且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会返回IListICollection,但不会提及由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);