只获取直接界面而不是全部?

时间:2011-03-15 22:07:32

标签: c# reflection

我有一个类似下面的课程。 GetInterfaces()说

  

如果当前Type表示类型   a的定义中的参数   通用类型或通用方法,这个   方法搜索界面   约束和任何接口   继承自类或接口   约束

我有可能没有获得任何继承的接口吗?当我在ABC上使用GetInterfaces时,我只想看DEF,而不是DEF和GHI。

interface DEF : GHI {...}
class ABC : DEF {...}

6 个答案:

答案 0 :(得分:28)

首先,您发布的MSDN代码段与您的实际问题没有任何关系。例如,当您拥有class Foo<T> where T : IEnumerable这样的通用类型时,它会尝试在类型参数GetInterfaces上调用T,例如通过typeof(Foo<>).GetGenericArguments().Single().GetInterfaces(). < / p>

其次,问题略显不明。请注意,当类实现接口时,它必须实现该接口继承的所有接口。它只是一个C#便利功能,可以省略类声明中的继承接口。在您的示例中,显式包含“继承的”GHI接口完全合法(并且没有区别):

class ABC : DEF, GHI {...}

我认为你真正想要做的是找到一个“覆盖”所有类型实现接口的“最小集合”接口。这导致Set cover problem的略微简化版本。

这是解决它的一种方法,没有任何尝试在算法上有效。我们的想法是通过过滤那些已由实现的接口来生成最小接口集。由该类型实现的其他接口。

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<int>

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 '层次结构'(这是您想要的),而不是它们与类的层次结构的关系。特别是,它不关注在类的层次结构中首先实现接口。

例如,假设我们有:

interface IFoo { }
interface IBar : IFoo { }
interface IBaz { } 

class Base : IBar {  }
class Derived : Base, IBaz {  }

现在,如果您尝试使用我所描述的解决方案来获取Derived的最小接口集,那么您将获得IBaz以及IBar。如果您不想要IBar,则必须付出更多努力:消除基类实现的接口。最简单的方法是从最小的接口集中删除由类的直接基类实现的接口,如@ MikeEast的答案中所述。

答案 1 :(得分:3)

这是来自duplicate question

的精彩内容
public static class TypeExtensions {
   public static IEnumerable<Type> 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);
}

答案 2 :(得分:0)

相同的MSDN页面说

  

GetInterfaces方法没有   返回特定的接口   顺序,如字母或   申报单。你的代码一定不能   取决于其中的顺序   返回接口,因为那样   订单各不相同。

所以不,你不能跳过接口。

答案 3 :(得分:0)

接口继承层次结构如何?

    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<Map> Ancestors { get; set; }
    }

答案 4 :(得分:0)

此问题与herehere都重复。无论如何,这里是我的简明代码,它考虑了@Ani和@Mikael在这个帖子中提出的观点:

var actualInterfaces = type.GetInterfaces();
foreach ( var result in actualInterfaces
    .Except( type.BaseType?.GetInterfaces() ?? Enumerable.Empty<Type>() ) //See https://stackoverflow.com/a/1613936
    .Except( actualInterfaces.SelectMany( i => i.GetInterfaces() ) ) //See https://stackoverflow.com/a/5318781
) yield return result;

答案 5 :(得分:0)

据我所知,在下面的示例中,没有发布的解决方案适用于typeof(C1)typeof(I3)

我认为正确的答案是不可能使用现成的框架调用来获得直接实现的接口。

private interface I1 { }

private interface I2 : I1 { }

private interface I3 : I2, I1 { }

public class C1 : I3, I1 { }