【问题标题】:Get only direct interface instead of all?只获取直接接口而不是全部?
【发布时间】:2011-03-15 22:07:31
【问题描述】:

我有一个像下面这样的课程。 GetInterfaces() 说

如果当前Type代表一个类型 a 定义中的参数 泛型类型或泛型方法,this 方法搜索接口 约束和任何接口 从类或接口继承 约束。

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

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

【问题讨论】:

  • 自从我m only on my iPad I cant 测试代码或查找所有方法,但这里s a thought. Could you find all the interfaces your type implements (including inherites ones), then move on to the base type of your type, find all the interfaces *that* type implements, and subtract those from the first set? I would think you would be left with what ABC itself added of interfaces. If anyone wants to "steal" this comment and type up a real answer of it, please do, it wont 等到明天,直到我回到我的电脑。
  • GetInterfaces() 是 Type 类的方法。
  • 啊,对不起,你的“基础类型”是接口,那我就不知道了。
  • @Lasse:我对这个问题的理解不同;我认为 OP 只对接口层次结构感兴趣。

标签: c# reflection


【解决方案1】:

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

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

class ABC : DEF, GHI {...}

我假设您真正想要做的是找到“覆盖”该类型的所有已实现接口的“最小集”接口。这导致了Set cover problem 的略微简化版本。

这是解决它的一种方法,无需任何尝试提高算法效率。这个想法是通过过滤掉那些已经由该类型实现的other接口实现的接口来生成最小接口集。

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

例如,假设我们有:

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

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

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

【讨论】:

    【解决方案2】:

    这是来自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);
    }
    

    【讨论】:

    • 问题在于它不适用于IList&lt;string&gt;,我有一个基于@Lasse 评论的类似解决方案
    • 啊,对于BaseType 的事情。没看到那个。
    【解决方案3】:

    据我所知,以下示例中的typeof(C1)typeof(I3) 都没有发布的解决方案。

    我认为正确的答案是无法使用开箱即用的框架调用来获得直接实现的接口。

    private interface I1 { }
    
    private interface I2 : I1 { }
    
    private interface I3 : I2, I1 { }
    
    public class C1 : I3, I1 { }
    

    【讨论】:

      【解决方案4】:

      接口继承heirachy怎么样?

          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; }
          }
      

      【讨论】:

        【解决方案5】:

        同一个 MSDN 页面说

        GetInterfaces 方法不 返回特定的接口 顺序,例如按字母顺序或 申报令。您的代码不得 取决于其中的顺序 返回接口,因为 顺序不同。

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

        【讨论】:

        • OP 不会尝试跳过接口,而是仅检索直接实现的接口。
        • 我认为这里的主要问题是,一旦一个类型实现了一个接口,s no concept of "directly implemented" any more. Youll 必须分析接口“继承”的图并找到最合理的结果。
        【解决方案6】:

        这个问题在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;
        

        【讨论】:

          猜你喜欢
          • 2018-01-24
          • 1970-01-01
          • 2017-02-02
          • 2016-02-25
          • 2022-07-30
          • 2018-08-10
          • 2012-04-14
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多